diff options
-rw-r--r-- | Makefile.example | 1 | ||||
-rw-r--r-- | Makefile.test | 3 | ||||
-rw-r--r-- | Makefile.util | 3 | ||||
-rw-r--r-- | examples/example2a_measure_time_wasm/Makefile | 3 | ||||
-rw-r--r-- | examples/example2a_measure_time_wasm/instructions.wat | 110 | ||||
l--------- | examples/example2b_measure_time_wasm/Makefile | 1 | ||||
-rw-r--r-- | examples/example2b_measure_time_wasm/instructions.wat | 112 | ||||
-rw-r--r-- | examples/example_toplevel.v | 5 |
8 files changed, 235 insertions, 3 deletions
diff --git a/Makefile.example b/Makefile.example index e44cf9c..c85dc8f 100644 --- a/Makefile.example +++ b/Makefile.example @@ -26,6 +26,7 @@ example.vvp : $(DESIGN_DIR)/*.v soc_with_peripherals.v flash_memory.v sram.v \ simulate : example.vvp $(VVP) $< + if [ -f VGAdump.mem ]; then $(MAKE) VGAdump.ppm; fi design.v : instructions.mem $(DESIGN_DIR)/*.v $(FONT) $(IV) $(IVFLAGS) $(ROM_DEFINES) -E $(filter %.v,$^) -o $@ diff --git a/Makefile.test b/Makefile.test index d6ac8ab..8427465 100644 --- a/Makefile.test +++ b/Makefile.test @@ -53,9 +53,6 @@ endif report.log VGAdump.mem : test.vvp $(VVP) $< | $(call DBG&SAVE,report.log) -VGAdump.ppm : $(PROJ_DIR)/tools/VGAdump2ppm VGAdump.mem - grep -v // < VGAdump.mem | $< > $@ - clean : find . -name "*.vvp" -delete rm $(call FIND_GENERATED_FILES,.) report.log VGAdump.mem \ diff --git a/Makefile.util b/Makefile.util index 4abddca..88939b1 100644 --- a/Makefile.util +++ b/Makefile.util @@ -67,4 +67,7 @@ FIND_GENERATED_FILES = \ $(call FIND_GENERATED_MEM_FILES,$(1)) \ $(call FIND_GENERATED_WASM_FILES,$(1)) +VGAdump.ppm : $(PROJ_DIR)/tools/VGAdump2ppm VGAdump.mem + grep -v // < VGAdump.mem | $< > $@ + .PHONY : prog diff --git a/examples/example2a_measure_time_wasm/Makefile b/examples/example2a_measure_time_wasm/Makefile new file mode 100644 index 0000000..a454260 --- /dev/null +++ b/examples/example2a_measure_time_wasm/Makefile @@ -0,0 +1,3 @@ +SIMFLAGS += -DFINISH_ON_LED1=1 -DFINISH_ON_LED2=1 -DFINISH_ON_IMAGE_WRITES=1 + +include ../../Makefile.example diff --git a/examples/example2a_measure_time_wasm/instructions.wat b/examples/example2a_measure_time_wasm/instructions.wat new file mode 100644 index 0000000..3a6be34 --- /dev/null +++ b/examples/example2a_measure_time_wasm/instructions.wat @@ -0,0 +1,110 @@ +;; See instructions.wat of soc_print_number test. A lot has been taken from +;; there. +;; Relevant addresses are VGA text memory (0xFFC00), VGA regs (0x100600), +;; lower half of timer reg (0x1BFC08) and led2 reg (0x1BFC06). + +(module + (memory 0 2) + ;; print number in decimal at address $dest, return address after + ;; the last digit + (func $print (param $number i32) (param $dest i32) (result i32) + (local $adr1 i32) + (local $adr2 i32) + ;; remember the initial address to write at + (set_local $adr1 (get_local $dest)) + (loop $again + ;; prepare address for store operation later + (get_local $dest) + ;; compute the last digit of number + (i32.rem_u (get_local $number) + (i32.const 10)) + ;; 0x30 is ASCII encoding of digit 0 + (i32.add (i32.const 0x30)) + ;; write digit's ASCII char to memory + (i32.store8 offset=0x0 align=1) + ;; increment the pointer + (set_local $dest (i32.add (i32.const 1) + (get_local $dest))) + ;; divide our number by 10 + (set_local $number (i32.div_u (get_local $number) + (i32.const 10))) + ;; break the loop, if number is 0 + (br_if $again (get_local $number))) + + ;; digit chars are now in the reverse order - swap them in a loop + (set_local $adr2 (i32.sub (get_local $dest) + (i32.const 1))) + (loop $again + ;; prepare address for later store operation + (get_local $adr2) + ;; load value on the left + (i32.load8_u offset=0x0 align=1 + (get_local $adr1)) + ;; prepare address for later store operation + (get_local $adr1) + ;; load value on the right + (i32.load8_u offset=0x0 align=1 + (get_local $adr2)) + ;; write value on the left + (i32.store8 offset=0x0 align=1) + ;; write value on the right + (i32.store8 offset=0x0 align=1) + + ;; increase $adr1 + (set_local $adr1 (i32.add (get_local $adr1) + (i32.const 1))) + ;; decrease $adr2 + (set_local $adr2 (i32.sub (get_local $adr2) + (i32.const 1))) + ;; loop until adr1 and adr2 cross/meet + (br_if $again (i32.lt_u (get_local $adr1) + (get_local $adr2)))) + ;; return the address we finished at + (get_local $dest)) + (func $main + (local $counter i32) + (local $adr i32) + + ;; reset the timer (although it should already be resetted, anyway...) + (i32.store16 offset=0x1BFC08 align=1 + (i32.const 0x0) (i32.const 0x0)) + + ;; initialize counter + (set_local $counter (i32.const 0)) + + ;; add numbers from 1 to 100 + (i32.const 0) + (loop $again (param i32) (result i32) + (set_local $counter (i32.add + (get_local $counter) + (i32.const 1))) + (i32.add (get_local $counter)) + (br_if $again (i32.lt_u + (get_local $counter) + (i32.const 100)))) + ;; we now leave sum on the stack for later + + ;; light led2 + (i32.store16 offset=0x1BFC06 align=1 + (i32.const 0x0) (i32.const 0x1)) + + ;; print timer value + (set_local $adr (call $print + ;; read timer value + (i32.load16_u offset=0x1BFC08 align=1 + (i32.const 0x0)) + (i32.const 0xFFC00))) + + ;; print ascii underscore '_' + (i32.store8 offset=0x0 align=1 + (get_local $adr) (i32.const 0x5F)) + + ;; print computed sum + (set_local $adr (call $print + ;; sum's already on the stack + (i32.add (get_local $adr) (i32.const 1)))) + + ;; write a non-zero value to the VGA power-on reg at 0x100600 (0x100A00) + (i32.store16 offset=0x100600 align=2 + (i32.const 0) (i32.const 1))) + (export "main" (func $main))) diff --git a/examples/example2b_measure_time_wasm/Makefile b/examples/example2b_measure_time_wasm/Makefile new file mode 120000 index 0000000..1dcc8e9 --- /dev/null +++ b/examples/example2b_measure_time_wasm/Makefile @@ -0,0 +1 @@ +../example2a_measure_time_wasm/Makefile
\ No newline at end of file diff --git a/examples/example2b_measure_time_wasm/instructions.wat b/examples/example2b_measure_time_wasm/instructions.wat new file mode 100644 index 0000000..6107b30 --- /dev/null +++ b/examples/example2b_measure_time_wasm/instructions.wat @@ -0,0 +1,112 @@ +;; See instructions.wat of soc_print_number test. A lot has been taken from +;; there. +;; Relevant addresses are VGA text memory (0xFFC00), VGA regs (0x100600), +;; lower half of timer reg (0x1BFC08) and led2 reg (0x1BFC06). + +(module + (memory 0 2) + ;; print number in decimal at address $dest, return address after + ;; the last digit + (func $print (param $number i32) (param $dest i32) (result i32) + (local $adr1 i32) + (local $adr2 i32) + ;; remember the initial address to write at + (set_local $adr1 (get_local $dest)) + (loop $again + ;; prepare address for store operation later + (get_local $dest) + ;; compute the last digit of number + (i32.rem_u (get_local $number) + (i32.const 10)) + ;; 0x30 is ASCII encoding of digit 0 + (i32.add (i32.const 0x30)) + ;; write digit's ASCII char to memory + (i32.store8 offset=0x0 align=1) + ;; increment the pointer + (set_local $dest (i32.add (i32.const 1) + (get_local $dest))) + ;; divide our number by 10 + (set_local $number (i32.div_u (get_local $number) + (i32.const 10))) + ;; break the loop, if number is 0 + (br_if $again (get_local $number))) + + ;; digit chars are now in the reverse order - swap them in a loop + (set_local $adr2 (i32.sub (get_local $dest) + (i32.const 1))) + (loop $again + ;; prepare address for later store operation + (get_local $adr2) + ;; load value on the left + (i32.load8_u offset=0x0 align=1 + (get_local $adr1)) + ;; prepare address for later store operation + (get_local $adr1) + ;; load value on the right + (i32.load8_u offset=0x0 align=1 + (get_local $adr2)) + ;; write value on the left + (i32.store8 offset=0x0 align=1) + ;; write value on the right + (i32.store8 offset=0x0 align=1) + + ;; increase $adr1 + (set_local $adr1 (i32.add (get_local $adr1) + (i32.const 1))) + ;; decrease $adr2 + (set_local $adr2 (i32.sub (get_local $adr2) + (i32.const 1))) + ;; loop until adr1 and adr2 cross/meet + (br_if $again (i32.lt_u (get_local $adr1) + (get_local $adr2)))) + ;; return the address we finished at + (get_local $dest)) + (func $add (param $number1 i32) (param $number2 i32) (result i32) + (i32.add (get_local $number1) (get_local $number2))) + (func $main + (local $counter i32) + (local $adr i32) + + ;; reset the timer (although it should already be resetted, anyway...) + (i32.store16 offset=0x1BFC08 align=1 + (i32.const 0x0) (i32.const 0x0)) + + ;; initialize counter + (set_local $counter (i32.const 0)) + + ;; add numbers from 1 to 100 + (i32.const 0) + (loop $again (param i32) (result i32) + (set_local $counter (call $add + (get_local $counter) + (i32.const 1))) + (i32.add (get_local $counter)) + (br_if $again (i32.lt_u + (get_local $counter) + (i32.const 100)))) + ;; we now leave sum on the stack for later + + ;; light led2 + (i32.store16 offset=0x1BFC06 align=1 + (i32.const 0x0) (i32.const 0x1)) + + ;; print timer value + (set_local $adr (call $print + ;; read timer value + (i32.load16_u offset=0x1BFC08 align=1 + (i32.const 0x0)) + (i32.const 0xFFC00))) + + ;; print ascii underscore '_' + (i32.store8 offset=0x0 align=1 + (get_local $adr) (i32.const 0x5F)) + + ;; print computed sum + (set_local $adr (call $print + ;; sum's already on the stack + (i32.add (get_local $adr) (i32.const 1)))) + + ;; write a non-zero value to the VGA power-on reg at 0x100600 (0x100A00) + (i32.store16 offset=0x100600 align=2 + (i32.const 0) (i32.const 1))) + (export "main" (func $main))) diff --git a/examples/example_toplevel.v b/examples/example_toplevel.v index 1da1750..3359bb3 100644 --- a/examples/example_toplevel.v +++ b/examples/example_toplevel.v @@ -125,6 +125,11 @@ module example(); end end + always @ (image_writes) begin + if (image_writes) + `MSG(("Display refreshed %0d times", image_writes)); + end + generate if (`FINISH_RULE_PROVIDED) begin always @ (image_writes or led1 or led2 or can_finish) begin |