Skip to content

Commit

Permalink
WIP JTAG tracing
Browse files Browse the repository at this point in the history
  • Loading branch information
hydrolarus committed Jan 30, 2024
1 parent 3a4a420 commit 89885ba
Show file tree
Hide file tree
Showing 7 changed files with 6,142 additions and 44 deletions.
2 changes: 1 addition & 1 deletion clash-vexriscv-sim/src/Utils/Cpu.hs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ emptyInput =
}


createDomain vXilinxSystem{vName="Basic1", vPeriod= hzToPeriod 1e6}
createDomain vXilinxSystem{vName="Basic1", vPeriod= hzToPeriod 50_000}

{-
Address space
Expand Down
14 changes: 9 additions & 5 deletions clash-vexriscv/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ OUT_DIR = build_out_dir
VERILATOR_DIR = $(OUT_DIR)/verilator_output
FFI_DIR = src/ffi


VERILATOR_FLAGS = -CFLAGS '-O3 -fPIC' -Wno-fatal +1364-2001ext+v
VERILATOR_FLAGS = -CFLAGS '-O3 -fPIC' -Wno-fatal +1364-2001ext+v --trace

VERILATOR_CFLAGS = $(shell pkg-config --cflags verilator)
FFI_CPPFLAGS = $(VERILATOR_CFLAGS) -fPIC -O3 -I$(VERILATOR_DIR)
Expand All @@ -26,7 +25,7 @@ $(CPU_DIR)/VexRiscv.v: $(CPU_DIR)/src/main/scala/example/ExampleCpu.scala

$(OUT_DIR)/VexRiscv.v: $(CPU_DIR)/VexRiscv.v
mkdir -p $(OUT_DIR)
cp $(CPU_DIR)/VexRiscv.v $(OUT_DIR)/VexRiscv.v
cp $(CPU_DIR)/VexRiscvTrace.v $(OUT_DIR)/VexRiscv.v

$(VERILATOR_DIR)/VVexRiscv.mk $(VERILATOR_DIR)/VVexRiscv.h: $(OUT_DIR)/VexRiscv.v
cd $(OUT_DIR); verilator $(VERILATOR_FLAGS) --cc -Mdir ../$(VERILATOR_DIR) VexRiscv.v
Expand All @@ -37,19 +36,24 @@ $(VERILATOR_DIR)/VVexRiscv__ALL.a: $(VERILATOR_DIR)/VVexRiscv.mk
$(OUT_DIR)/impl.o: $(FFI_DIR)/impl.cpp $(FFI_DIR)/interface.h
$(CXX) $(FFI_CPPFLAGS) -c $(FFI_DIR)/impl.cpp -o $(OUT_DIR)/impl.o

$(OUT_DIR)/verilated_vcd_c.o: $(shell pkg-config --variable=includedir verilator)/verilated_vcd_c.cpp
$(CXX) $(FFI_CPPFLAGS) -c $(shell pkg-config --variable=includedir verilator)/verilated_vcd_c.cpp -o $(OUT_DIR)/verilated_vcd_c.o


$(OUT_DIR)/verilated.o: $(shell pkg-config --variable=includedir verilator)/verilated.cpp
$(CXX) $(FFI_CPPFLAGS) -c $(shell pkg-config --variable=includedir verilator)/verilated.cpp -o $(OUT_DIR)/verilated.o

$(OUT_DIR)/VVexRiscv__ALL.a: $(VERILATOR_DIR)/VVexRiscv__ALL.a
cp $(VERILATOR_DIR)/VVexRiscv__ALL.a $(OUT_DIR)/VVexRiscv__ALL.a

$(OUT_DIR)/libVexRiscvFFI.a: $(OUT_DIR)/VVexRiscv__ALL.a $(OUT_DIR)/impl.o $(OUT_DIR)/verilated.o
$(OUT_DIR)/libVexRiscvFFI.a: $(OUT_DIR)/VVexRiscv__ALL.a $(OUT_DIR)/impl.o $(OUT_DIR)/verilated.o $(OUT_DIR)/verilated_vcd_c.o
rm -f $(OUT_DIR)/libVexRiscvFFI.a
cp $(OUT_DIR)/VVexRiscv__ALL.a $(OUT_DIR)/libVexRiscvFFI.a
ar r \
$(OUT_DIR)/libVexRiscvFFI.a \
$(OUT_DIR)/impl.o \
$(OUT_DIR)/verilated.o
$(OUT_DIR)/verilated.o \
$(OUT_DIR)/verilated_vcd_c.o

$(OUT_DIR)/libVexRiscvFFI.so: $(OUT_DIR)/libVexRiscvFFI.a
rm -f $(OUT_DIR)/libVexRiscvFFI.so
Expand Down
6,031 changes: 6,031 additions & 0 deletions clash-vexriscv/example-cpu/VexRiscvTrace.v

Large diffs are not rendered by default.

113 changes: 79 additions & 34 deletions clash-vexriscv/src/VexRiscv.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,18 @@ import Clash.Prelude

import Clash.Annotations.Primitive
import Clash.Signal.Internal
import Clash.Signal (ActiveEdge(..))
import Control.Monad (when)
import Data.String.Interpolate (__i)
import Data.Word
import Foreign.Marshal (alloca)
import Foreign.Storable
import GHC.IO (unsafePerformIO)
import GHC.Stack (HasCallStack)
import Language.Haskell.TH.Syntax
import Protocols
import Protocols.Wishbone
import VexRiscv.ClockTicks
import VexRiscv.FFI
import VexRiscv.TH
import Debug.Trace (trace)
Expand Down Expand Up @@ -330,52 +334,88 @@ vexRiscv# !_sourcePath clk rst0
iBusS2M = WishboneS2M <$> iBus_DAT_MISO <*> iBus_ACK <*> iBus_ERR <*> pure False <*> pure False
dBusS2M = WishboneS2M <$> dBus_DAT_MISO <*> dBus_ACK <*> dBus_ERR <*> pure False <*> pure False

flattenedTicks = go (clockTicks clk jtag_TCK)
ticks = go $ clockEdgesRelative clk jtag_TCK
where
go [] = error "Clock tick list should be infinite"
go (ClockA : rest) = ClockA : go rest
go (ClockB : rest) = ClockB : go rest
go (ClockAB : rest) = ClockA : ClockB : go rest
go ((wordCast -> t, ClockEdgeA edge) : rest) = cpuEdge edge : AdvanceTime t : go rest
go ((wordCast -> t, ClockEdgeB edge) : rest) = jtagEdge edge : AdvanceTime t : go rest
go ((wordCast -> t, ClockEdgeAB edgeA edgeB) : rest) = cpuEdge edgeA : jtagEdge edgeB : AdvanceTime t : go rest

wordCast x = fromInteger $ toInteger x

cpuEdge Rising = CpuRising
cpuEdge Falling = CpuFalling

jtagEdge Rising = JtagRising
jtagEdge Falling = JtagFalling

-- The `[ClockSimOrder]` gets consumed twice as fast as the signals produce
-- and consume values.
--
-- That means that values in the output signal will be produced in the
-- "falling" cases. Values in the input signals will also be consued in the
-- "falling" cases.
bothOutputs ::
[ClockAB] ->
Bool -> -- ^ CLK asserted
Bool -> -- ^ TCK asserted
[ClockSimOrder] ->
Bool -> -- ^ JTAG_ENABLED asserted
Signal domCpu Bool -> -- ^ reset
Signal domCpu Input ->
Signal domJtag Bool -> -- ^ enable
Signal domJtag JtagIn ->
(Signal domCpu Output, Signal domJtag JtagOut)
bothOutputs (ClockA:ticks) clkAsserted tckAsserted (r :- rsts) (c :- cpuIn) jtagEn jtagIn
| clkAsserted =
let (cpuSig, jtagSig) = bothOutputs ticks False tckAsserted rsts cpuIn jtagEn jtagIn
!cpuOut = unsafePerformIO $ cpuStepFalling v
in
cpuOut `deepseqX` (cpuOut :- (cpuOut `deepseqX` cpuSig), jtagSig)
| otherwise =
let (cpuSig, jtagSig) = bothOutputs ticks True tckAsserted (r :- rsts) (c :- cpuIn) jtagEn jtagIn in
unsafePerformIO (cpuStepRising v r c) `deepseqX`
(cpuSig, jtagSig)

bothOutputs (ClockB:ticks) clkAsserted tckAsserted rsts cpuIn (en :- enables) (j :- jtagIn)
| tckAsserted =
let (cpuSig, jtagSig) = bothOutputs ticks clkAsserted False rsts cpuIn enables jtagIn in

let !jtagOut = if en
then unsafePerformIO $ jtagStepFalling v
else JtagOut { testDataOut = low, debugReset = low }
bothOutputs (CpuRising:ticks) tckAsserted (r :- rsts) (c :- cpuIn) jtagEn jtagIn =
let (cpuSig, jtagSig) = bothOutputs ticks tckAsserted (r :- rsts) (c :- cpuIn) jtagEn jtagIn in
unsafePerformIO (cpuStepRising v r c) `deepseqX`
(cpuSig, jtagSig)

bothOutputs (CpuFalling:ticks) tckAsserted (r :- rsts) (c :- cpuIn) jtagEn jtagIn =
let (cpuSig, jtagSig) = bothOutputs ticks tckAsserted rsts cpuIn jtagEn jtagIn
!cpuOut = unsafePerformIO $ cpuStepFalling v
in
cpuOut `deepseqX` (cpuOut :- (cpuOut `deepseqX` cpuSig), jtagSig)

bothOutputs (JtagRising:ticks) tckAsserted rsts cpuIn (en :- enables) (j :- jtagIn)
| tckAsserted && en =
-- do nothing
bothOutputs ticks tckAsserted rsts cpuIn (en :- enables) (j :- jtagIn)
| tckAsserted && not en =
-- do nothing, pass to falling edge
bothOutputs ticks tckAsserted rsts cpuIn (en :- enables) (j :- jtagIn)
| not tckAsserted && en =
-- do rising edge
let (cpuSig, jtagSig) = bothOutputs ticks True rsts cpuIn (en :- enables) (j :- jtagIn) in

-- trace "!TCK" $
unsafePerformIO (jtagStepRising v j) `deepseqX` (cpuSig, jtagSig)

| not tckAsserted && not en =
-- do nothing
bothOutputs ticks tckAsserted rsts cpuIn (en :- enables) (j :- jtagIn)
bothOutputs (JtagFalling:ticks) tckAsserted rsts cpuIn (en :- enables) (j :- jtagIn)
| not tckAsserted && en =
-- shouldn't happen, if en then there should be a rising edge => TCK
error "!TCK && EN shouldn't happen at a falling edge"
| not tckAsserted && not en =
-- don't need to do anything
let (cpuSig, jtagSig) = bothOutputs ticks tckAsserted rsts cpuIn enables jtagIn
in (cpuSig, JtagOut low low :- jtagSig)
| tckAsserted && en =
-- don't need to do anything
let (cpuSig, jtagSig) = bothOutputs ticks tckAsserted rsts cpuIn enables jtagIn
in (cpuSig, JtagOut low low :- jtagSig)
| tckAsserted && not en =
-- actually do falling edge
let (cpuSig, jtagSig) = bothOutputs ticks False rsts cpuIn enables jtagIn
!jtagOut = unsafePerformIO $ jtagStepFalling v
in
-- trace " TCK" $
(cpuSig, jtagOut :- (jtagOut `deepseqX` jtagSig))

bothOutputs (AdvanceTime t:ticks) tckAsserted rsts cpuIn jtagEn jtagIn =
unsafePerformIO (vexrSimTimeStep t) `deepseqX`
bothOutputs ticks tckAsserted rsts cpuIn jtagEn jtagIn

| otherwise =
let (cpuSig, jtagSig) = bothOutputs ticks clkAsserted True rsts cpuIn (en :- enables) (j :- jtagIn) in

unsafePerformIO (jtagStepRising v j) `deepseqX` (cpuSig, jtagSig)

bothOutputs (ClockAB:_ticks) _ _ _rsts _cpuIn _jtagEn _jtagIn = error "ClockAB should not happen"
bothOutputs [] _ _ _ _ _ _ = error "Clock tick list should be infinite"
bothOutputs [] _ _ _ _ _ = error "Clock tick list should be infinite"


cpuInput = Input <$> timerInterrupt <*> externalInterrupt <*> softwareInterrupt <*> iBusS2M <*> dBusS2M
Expand All @@ -384,8 +424,7 @@ vexRiscv# !_sourcePath clk rst0

(cpuOutput, jtagOutput) =
bothOutputs
flattenedTicks
False
ticks
False
(unsafeToActiveHigh rst0)
cpuInput
Expand Down Expand Up @@ -588,6 +627,12 @@ vexRiscv# !_sourcePath clk rst0
|] ) #-}


data ClockSimOrder = CpuRising
| CpuFalling
| JtagRising
| JtagFalling
| AdvanceTime Word64

-- | Return a function that performs an execution step and a function to free
-- the internal CPU state
vexCPU :: IO
Expand Down
1 change: 1 addition & 0 deletions clash-vexriscv/src/VexRiscv/FFI.hsc
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ foreign import ccall unsafe "vexr_cpu_step_falling_edge" vexrCpuStepFallingEdge
foreign import ccall unsafe "vexr_jtag_step_rising_edge" vexrJtagStepRisingEdge :: Ptr VexRiscv -> Ptr JTAG_INPUT -> IO ()
foreign import ccall unsafe "vexr_jtag_step_falling_edge" vexrJtagStepFallingEdge :: Ptr VexRiscv -> Ptr JTAG_OUTPUT -> IO ()

foreign import ccall unsafe "vexr_sim_time_step" vexrSimTimeStep :: Word64 -> IO ()

foreign import ccall unsafe "vexr_jtag_bridge_init" vexrJtagBridgeInit :: Word16 -> IO (Ptr VexRiscvJtagBridge)
foreign import ccall unsafe "vexr_jtag_bridge_step" vexrJtagBridgeStep :: Ptr VexRiscvJtagBridge -> Ptr JTAG_OUTPUT -> Ptr JTAG_INPUT -> Ptr Bit -> IO ()
Expand Down
23 changes: 20 additions & 3 deletions clash-vexriscv/src/ffi/impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ extern "C" {
void vexr_shutdown(VVexRiscv *top);
void vexr_cpu_step_rising_edge(VVexRiscv *top, const INPUT *input);
void vexr_cpu_step_falling_edge(VVexRiscv *top, OUTPUT *output);

void vexr_sim_time_step(uint64_t add);

void vexr_jtag_step_rising_edge(VVexRiscv *top, const JTAG_INPUT *input);
void vexr_jtag_step_falling_edge(VVexRiscv *top, JTAG_OUTPUT *output);
Expand All @@ -45,14 +47,26 @@ extern "C" {
static bool set_socket_blocking_enabled(int fd, bool blocking);
static void connection_reset(vexr_jtag_bridge_data *bridge_data);

static VerilatedContext* contextp = 0;

VVexRiscv* vexr_init()
{
return new VVexRiscv();
contextp = new VerilatedContext;
VVexRiscv *v = new VVexRiscv(contextp);
Verilated::traceEverOn(true);
return v;
}

void vexr_shutdown(VVexRiscv *top)
{
delete top;
delete contextp;
contextp = 0;
}

void vexr_sim_time_step(uint64_t add)
{
contextp->timeInc(add);
}

void vexr_cpu_step_rising_edge(VVexRiscv *top, const INPUT *input)
Expand All @@ -72,6 +86,7 @@ void vexr_cpu_step_rising_edge(VVexRiscv *top, const INPUT *input)
// run one cycle of the simulation
top->clk = true;
top->eval();

}

void vexr_cpu_step_falling_edge(VVexRiscv *top, OUTPUT *output)
Expand Down Expand Up @@ -174,7 +189,7 @@ void vexr_jtag_bridge_step(vexr_jtag_bridge_data *d, const JTAG_OUTPUT *output,
return;
}
d->check_new_connections_timer++;
if (d->check_new_connections_timer == 5000) {
if (d->check_new_connections_timer == 500) {
d->check_new_connections_timer = 0;
int new_client_handle = accept(
d->server_socket,
Expand All @@ -186,9 +201,10 @@ void vexr_jtag_bridge_step(vexr_jtag_bridge_data *d, const JTAG_OUTPUT *output,
connection_reset(d);
}
d->client_handle = new_client_handle;
printf("[JTAG BRIDGE] got new connection\n");
} else {
if(d->client_handle == -1)
d->self_sleep = 1000;
d->self_sleep = 200;
}
}
if (d->self_sleep) {
Expand Down Expand Up @@ -261,6 +277,7 @@ static bool set_socket_blocking_enabled(int fd, bool blocking)
}

static void connection_reset(vexr_jtag_bridge_data *bridge_data) {
printf("[JTAG BRIDGE] closed connection\n");
shutdown(bridge_data->client_handle, SHUT_RDWR);
bridge_data->client_handle = -1;
}
2 changes: 1 addition & 1 deletion vexriscv_sim.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
adapter driver jtag_tcp
adapter speed 1000
adapter speed 50
transport select jtag


Expand Down

0 comments on commit 89885ba

Please sign in to comment.