~charles/awk-riscv

19957547cb6e902a56ee294f9a9be8ffd3c7f613 — Charles Daniels 10 months ago b64c256
implement lw and sw
3 files changed, 77 insertions(+), 4 deletions(-)

M riscv.awk
A tests/simulation/lwsw.txt
A tests/unit/immS.tsv
M riscv.awk => riscv.awk +25 -4
@@ 90,6 90,11 @@
#	Asserts that the register REG contains a value equal to the given
#	32-bit value VAL.
#
# assert mem ADDR VAL
#
#	Asserts that the memory at address contains a value equal to the given
#	32-bit value VAL.
#
# step N
#
#	Advances the CPU simulation by N many cycles.


@@ 102,7 107,7 @@
#
#	Displays the value of the specified field FIELD of the instruction
#	literal INST. FIELD may take any of the following values: funct7, rs2,
#	rs1, fucnt3, rd, opcode, immI, immU, shamt, arith, immB, immJ.
#	rs1, fucnt3, rd, opcode, immI, immU, shamt, arith, immB, immJ, immS.
#
# debug disasm INST
#


@@ 204,6 209,9 @@ function immI(v)   { return signextend(rshift(and(v, 0xfff00000), 20), 11) }
function immU(v)   { return rshift(and(v, 0xfffff000),  0) }
function shamt(v)  { return rshift(and(v, 0x01f00000), 20) }
function arith(v)  { return rshift(and(v, 0x40000000), 30) }
function immS(v) { return signextend(or( \
	rshift(and(v, 0xfe000000), 20), \
	rshift(and(v, 0x00000f80), 7)), 11) }
function immB(v)   { return signextend(or( \
	rshift(and(v, 0x80000000), 31-12), \
	rshift(and(v, 0x7e000000), 25-5),  \


@@ 381,7 389,7 @@ function memwrite(memaddr, v) {
# Reads a 32 bit value from the given memory address, re-composing the 1 byte
# memory values into an 32 bit value automatically.
function memread(memaddr,      res) {
	res = or(lshift(and(mem[PC], 0xff), 0), lshift(and(mem[PC+1], 0xff), 8), lshift(and(mem[PC+2], 0xff), 16), lshift(and(mem[PC+3], 0xff), 24))
	res = or(lshift(and(mem[memaddr], 0xff), 0), lshift(and(mem[memaddr+1], 0xff), 8), lshift(and(mem[memaddr+2], 0xff), 16), lshift(and(mem[memaddr+3], 0xff), 24))
	if (tracemem) {
		printf("memread(0x%08x) -> 0x%08x\n", memaddr, res)
	}


@@ 463,6 471,10 @@ function nextstate(    inst, branchtarget) {
	else if (op2str(inst) == "BGE" ) { if (two2dec(regread(rs1(inst))) >= two2dec(regread(rs2(inst)))) { PC_NEXT = branchtarget } }
	else if (op2str(inst) == "BGEU") { if (regread(rs1(inst)) >= regread(rs2(inst))) {PC_NEXT = branchtarget } }

	# load and store
	else if (op2str(inst) == "LW") { regwrite(rd(inst), memread(regread(rs1(inst)) + immI(inst))) }
	else if (op2str(inst) == "SW") { memwrite(regread(rs1(inst)) + immS(inst), regread(rs2(inst))) }

	PC = PC_NEXT
}



@@ 520,13 532,21 @@ $1 == "rpoke" { regwrite(strtonum($2), strtonum($3)) ; next }
$1 == "rpeek" { printf("0x%08x\n", regread(strtonum($2))) ; next }

$1 == "assert" && $2 == "reg" {
	assert_val = regread(strtonum($3))
	if (assert_val  != strtonum($4)) {
	assert_val = dec2two(regread(strtonum($3)))
	if (assert_val  != dec2two(strtonum($4))) {
		printf("ASSERTION FAILURE: register x%d was 0x%08x, should have been 0x%08x\n", strtonum($3), assert_val, strtonum($4))
		assert_errors ++
	}
}

$1 == "assert" && $2 == "mem" {
	assert_val = dec2two(memread(strtonum($3)))
	if (assert_val  != dec2two(strtonum($4))) {
		printf("ASSERTION FAILURE: memory at x%d was 0x%08x, should have been 0x%08x\n", strtonum($3), assert_val, strtonum($4))
		assert_errors ++
	}
}

$1 == "step" {
	howlong=strtonum($2)
	for ( ; howlong > 0; howlong--) {


@@ 591,6 611,7 @@ $1 == "debug" && $2 == "shamt" { printf("0x%08x\n", shamt(strtonum($3))); next }
$1 == "debug" && $2 == "arith" { printf("0x%08x\n", arith(strtonum($3))); next }
$1 == "debug" && $2 == "immB" { printf("0x%08x\n", immB(strtonum($3))); next }
$1 == "debug" && $2 == "immJ" { printf("0x%08x\n", immJ(strtonum($3))); next }
$1 == "debug" && $2 == "immS" { printf("0x%08x\n", immS(strtonum($3))); next }
$1 == "debug" && $2 == "disasm" { printf("%s\n", disasm(strtonum($3))); next }

END {

A tests/simulation/lwsw.txt => tests/simulation/lwsw.txt +16 -0
@@ 0,0 1,16 @@
traceregs 1
traceinst 1
tracemem 1
poke 150 0x123

poke 0x000 0x03200293   # addi x5 x0 50
poke 0x004 0x0642a503   # lw x10 100(x5)
poke 0x008 0x0652ac23   # sw x5 120(x5)

step 100

assert reg 5 50
assert reg 10 0x123
assert mem 170 50

showregs

A tests/unit/immS.tsv => tests/unit/immS.tsv +36 -0
@@ 0,0 1,36 @@
# test cases for immS

# note the sign-extension
debug immS 0x80000000	0xfffff800

debug immS 0x40000000	0x00000400
debug immS 0x20000000	0x00000200
debug immS 0x10000000	0x00000100
debug immS 0x08000000	0x00000080
debug immS 0x04000000	0x00000040
debug immS 0x02000000	0x00000020
debug immS 0x01000000	0x00000000
debug immS 0x00800000	0x00000000
debug immS 0x00400000	0x00000000
debug immS 0x00200000	0x00000000
debug immS 0x00100000	0x00000000
debug immS 0x00080000	0x00000000
debug immS 0x00040000	0x00000000
debug immS 0x00020000	0x00000000
debug immS 0x00010000	0x00000000
debug immS 0x00008000	0x00000000
debug immS 0x00004000	0x00000000
debug immS 0x00002000	0x00000000
debug immS 0x00001000	0x00000000
debug immS 0x00000800	0x00000010
debug immS 0x00000400	0x00000008
debug immS 0x00000200	0x00000004
debug immS 0x00000100	0x00000002
debug immS 0x00000080	0x00000001
debug immS 0x00000040	0x00000000
debug immS 0x00000020	0x00000000
debug immS 0x00000010	0x00000000
debug immS 0x00000008	0x00000000
debug immS 0x00000004	0x00000000
debug immS 0x00000002	0x00000000
debug immS 0x00000001	0x00000000