Compare commits
No commits in common. "82e5862752c098838bb56faf42778ae2d2934b0d" and "043157c4d867ac476364e33cfc3873ceee8adefd" have entirely different histories.
82e5862752
...
043157c4d8
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,81 +0,0 @@
|
|||
|
||||
ARCH=riscv64-unknown-elf
|
||||
GNU_DIR=$(HOME)/riscv/riscv/
|
||||
GNU_BIN=$(GNU_DIR)/bin
|
||||
|
||||
|
||||
CC=$(GNU_BIN)/$(ARCH)-gcc
|
||||
CXX=$(GNU_BIN)/$(ARCH)-g++
|
||||
AS=$(GNU_BIN)/$(ARCH)-as
|
||||
LD=$(GNU_BIN)/$(ARCH)-ld
|
||||
OBJCOPY=$(GNU_BIN)/$(ARCH)-objcopy
|
||||
OBJDUMP=$(GNU_BIN)/$(ARCH)-objdump
|
||||
SIZE=$(GNU_BIN)/$(ARCH)-size
|
||||
AR=$(GNU_BIN)/$(ARCH)-ar
|
||||
RANLIB=$(GNU_BIN)/$(ARCH)-ranlib
|
||||
|
||||
|
||||
CFLAGS+=-ffreestanding
|
||||
CFLAGS+=-fno-pic
|
||||
CFLAGS+=-march=rv32i -mabi=ilp32
|
||||
CFLAGS+= -g
|
||||
|
||||
|
||||
LDFLAGS+=-nostdlib
|
||||
LDFLAGS+=-Wl,-Ttext=0x00000000
|
||||
|
||||
# see: https://github.com/riscv/riscv-gcc/issues/120
|
||||
#LDFLAGS+=-Wl,--no-relax
|
||||
|
||||
|
||||
|
||||
ASFLAGS+=$(CFLAGS)
|
||||
CXXFLAGS+=$(CFLAGS)
|
||||
|
||||
CLEAN_DIRS=$(SUBDIRS:%=clean-%)
|
||||
ALL_DIRS=$(SUBDIRS:%=all-%)
|
||||
|
||||
OBJDUMPFLAGS+=-Mnumeric,no-aliases
|
||||
|
||||
.PHONY: all clean world $(CLEAN_DIRS) $(ALL_DIRS)
|
||||
|
||||
|
||||
%.bin : %
|
||||
$(OBJCOPY) $< -O binary $@
|
||||
|
||||
%.lst : %
|
||||
$(OBJDUMP) $(OBJDUMPFLAGS) -dr --disassemble-all $< > $<.lst
|
||||
|
||||
% : %.o
|
||||
$(LINK.cc) $(LDFLAGS) -o $@ $^ $(LDLIBS)
|
||||
$(SIZE) -x -A $@
|
||||
|
||||
%.s: %.c
|
||||
$(COMPILE.c) -S -o $@ $<
|
||||
|
||||
%.s: %.cc
|
||||
$(COMPILE.cc) -S -o $@ $<
|
||||
|
||||
%.o: %.c
|
||||
$(COMPILE.c) -o $@ $<
|
||||
|
||||
%.o: %.cc
|
||||
$(COMPILE.cc) -o $@ $<
|
||||
|
||||
%.srec: %
|
||||
$(OBJCOPY) $< -O srec $@
|
||||
|
||||
|
||||
|
||||
|
||||
all:: $(ALL_DIRS)
|
||||
|
||||
clean:: $(CLEAN_DIRS)
|
||||
|
||||
$(ALL_DIRS)::
|
||||
$(MAKE) -C $(@:all-%=%) all
|
||||
|
||||
$(CLEAN_DIRS)::
|
||||
$(MAKE) -C $(@:clean-%=%) clean
|
||||
|
||||
world:: clean all
|
|
@ -2,19 +2,16 @@ TOP=./
|
|||
include $(TOP)/Make.rules
|
||||
|
||||
LDLIBS=
|
||||
#CFLAGS+=-O0 -g
|
||||
# CFLAGS+=-Og -ggdb3
|
||||
CFLAGS+=-O0 -ggdb3
|
||||
CFLAGS+=-O0 -g
|
||||
|
||||
LDFLAGS+=-Wl,--no-relax
|
||||
LDFLAGS+=-Wl,-Ttext=0x80000000,-Tdata=0x80010000
|
||||
# LDFLAGS+=-T murax_128k_ram.ld
|
||||
LDFLAGS+=-Wl,-Tdata=0x10000
|
||||
|
||||
PROGS=prog prog.bin prog.lst
|
||||
|
||||
all:: $(PROGS)
|
||||
|
||||
prog: _crt0.o _rvmain.o myfunc.o
|
||||
prog: _crt0.o _rvmain.o myfunc.o myfuncStruct.o myfuncStructOOP.o myfuncOOP.o
|
||||
$(LINK.cc) -o $@ $^ $(LDLIBS)
|
||||
$(SIZE) -A -x $@
|
||||
|
||||
|
|
543
cpp/Murax.scala
543
cpp/Murax.scala
|
@ -1,543 +0,0 @@
|
|||
package vexriscv.demo
|
||||
|
||||
import spinal.core._
|
||||
import spinal.lib._
|
||||
import spinal.lib.bus.amba3.apb._
|
||||
import spinal.lib.bus.misc.SizeMapping
|
||||
import spinal.lib.bus.simple.PipelinedMemoryBus
|
||||
import spinal.lib.com.jtag.Jtag
|
||||
import spinal.lib.com.spi.ddr.SpiXdrMaster
|
||||
import spinal.lib.com.uart._
|
||||
import spinal.lib.io.{InOutWrapper, TriStateArray}
|
||||
import spinal.lib.misc.{InterruptCtrl, Prescaler, Timer}
|
||||
import spinal.lib.soc.pinsec.{PinsecTimerCtrl, PinsecTimerCtrlExternal}
|
||||
import vexriscv.plugin._
|
||||
import vexriscv.{VexRiscv, VexRiscvConfig, plugin}
|
||||
import spinal.lib.com.spi.ddr._
|
||||
import spinal.lib.bus.simple._
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
import scala.collection.Seq
|
||||
|
||||
/**
|
||||
* Created by PIC32F_USER on 28/07/2017.
|
||||
*
|
||||
* Murax is a very light SoC which could work without any external component.
|
||||
* - ICE40-hx8k + icestorm => 53 Mhz, 2142 LC
|
||||
* - 0.37 DMIPS/Mhz
|
||||
* - 8 kB of on-chip ram
|
||||
* - JTAG debugger (eclipse/GDB/openocd ready)
|
||||
* - Interrupt support
|
||||
* - APB bus for peripherals
|
||||
* - 32 GPIO pin
|
||||
* - one 16 bits prescaler, two 16 bits timers
|
||||
* - one UART with tx/rx fifo
|
||||
*/
|
||||
|
||||
|
||||
case class MuraxConfig(coreFrequency : HertzNumber,
|
||||
onChipRamSize : BigInt,
|
||||
onChipRamHexFile : String,
|
||||
pipelineDBus : Boolean,
|
||||
pipelineMainBus : Boolean,
|
||||
pipelineApbBridge : Boolean,
|
||||
gpioWidth : Int,
|
||||
uartCtrlConfig : UartCtrlMemoryMappedConfig,
|
||||
xipConfig : SpiXdrMasterCtrl.MemoryMappingParameters,
|
||||
hardwareBreakpointCount : Int,
|
||||
cpuPlugins : ArrayBuffer[Plugin[VexRiscv]]){
|
||||
require(pipelineApbBridge || pipelineMainBus, "At least pipelineMainBus or pipelineApbBridge should be enable to avoid wipe transactions")
|
||||
val genXip = xipConfig != null
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
object MuraxConfig{
|
||||
def default : MuraxConfig = default(false, false)
|
||||
def default(withXip : Boolean = false, bigEndian : Boolean = false) = MuraxConfig(
|
||||
coreFrequency = 12 MHz,
|
||||
onChipRamSize = 128 kB,
|
||||
onChipRamHexFile = null,
|
||||
pipelineDBus = true,
|
||||
pipelineMainBus = false,
|
||||
pipelineApbBridge = true,
|
||||
gpioWidth = 32,
|
||||
xipConfig = ifGen(withXip) (SpiXdrMasterCtrl.MemoryMappingParameters(
|
||||
SpiXdrMasterCtrl.Parameters(8, 12, SpiXdrParameter(2, 2, 1)).addFullDuplex(0,1,false),
|
||||
cmdFifoDepth = 32,
|
||||
rspFifoDepth = 32,
|
||||
xip = SpiXdrMasterCtrl.XipBusParameters(addressWidth = 24, lengthWidth = 2)
|
||||
)),
|
||||
hardwareBreakpointCount = if(withXip) 3 else 0,
|
||||
cpuPlugins = ArrayBuffer( //DebugPlugin added by the toplevel
|
||||
new IBusSimplePlugin(
|
||||
resetVector = if(withXip) 0xF001E000l else 0x00000000l,
|
||||
cmdForkOnSecondStage = true,
|
||||
cmdForkPersistence = withXip, //Required by the Xip controller
|
||||
prediction = NONE,
|
||||
catchAccessFault = false,
|
||||
compressedGen = false,
|
||||
bigEndian = bigEndian
|
||||
),
|
||||
new DBusSimplePlugin(
|
||||
catchAddressMisaligned = false,
|
||||
catchAccessFault = false,
|
||||
earlyInjection = false,
|
||||
bigEndian = bigEndian
|
||||
),
|
||||
new CsrPlugin(CsrPluginConfig.smallest(mtvecInit = if(withXip) 0xE0040020l else 0x00000020l)),
|
||||
new DecoderSimplePlugin(
|
||||
catchIllegalInstruction = false
|
||||
),
|
||||
new RegFilePlugin(
|
||||
regFileReadyKind = plugin.SYNC,
|
||||
zeroBoot = false
|
||||
),
|
||||
new IntAluPlugin,
|
||||
new SrcPlugin(
|
||||
separatedAddSub = false,
|
||||
executeInsertion = false
|
||||
),
|
||||
new LightShifterPlugin,
|
||||
new HazardSimplePlugin(
|
||||
bypassExecute = false,
|
||||
bypassMemory = false,
|
||||
bypassWriteBack = false,
|
||||
bypassWriteBackBuffer = false,
|
||||
pessimisticUseSrc = false,
|
||||
pessimisticWriteRegFile = false,
|
||||
pessimisticAddressMatch = false
|
||||
),
|
||||
new BranchPlugin(
|
||||
earlyBranch = false,
|
||||
catchAddressMisaligned = false
|
||||
),
|
||||
new YamlPlugin("cpu0.yaml")
|
||||
),
|
||||
uartCtrlConfig = UartCtrlMemoryMappedConfig(
|
||||
uartCtrlConfig = UartCtrlGenerics(
|
||||
dataWidthMax = 8,
|
||||
clockDividerWidth = 20,
|
||||
preSamplingSize = 1,
|
||||
samplingSize = 3,
|
||||
postSamplingSize = 1
|
||||
),
|
||||
initConfig = UartCtrlInitConfig(
|
||||
baudrate = 115200,
|
||||
dataLength = 7, //7 => 8 bits
|
||||
parity = UartParityType.NONE,
|
||||
stop = UartStopType.ONE
|
||||
),
|
||||
busCanWriteClockDividerConfig = false,
|
||||
busCanWriteFrameConfig = false,
|
||||
txFifoDepth = 16,
|
||||
rxFifoDepth = 16
|
||||
)
|
||||
|
||||
)
|
||||
|
||||
def fast = {
|
||||
val config = default
|
||||
|
||||
//Replace HazardSimplePlugin to get datapath bypass
|
||||
config.cpuPlugins(config.cpuPlugins.indexWhere(_.isInstanceOf[HazardSimplePlugin])) = new HazardSimplePlugin(
|
||||
bypassExecute = true,
|
||||
bypassMemory = true,
|
||||
bypassWriteBack = true,
|
||||
bypassWriteBackBuffer = true
|
||||
)
|
||||
// config.cpuPlugins(config.cpuPlugins.indexWhere(_.isInstanceOf[LightShifterPlugin])) = new FullBarrelShifterPlugin()
|
||||
|
||||
config
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
case class Murax(config : MuraxConfig) extends Component{
|
||||
import config._
|
||||
|
||||
val io = new Bundle {
|
||||
//Clocks / reset
|
||||
val asyncReset = in Bool()
|
||||
val mainClk = in Bool()
|
||||
|
||||
//Main components IO
|
||||
val jtag = slave(Jtag())
|
||||
|
||||
//Peripherals IO
|
||||
val gpioA = master(TriStateArray(gpioWidth bits))
|
||||
val uart = master(Uart())
|
||||
|
||||
val xip = ifGen(genXip)(master(SpiXdrMaster(xipConfig.ctrl.spi)))
|
||||
}
|
||||
|
||||
|
||||
val resetCtrlClockDomain = ClockDomain(
|
||||
clock = io.mainClk,
|
||||
config = ClockDomainConfig(
|
||||
resetKind = BOOT
|
||||
)
|
||||
)
|
||||
|
||||
val resetCtrl = new ClockingArea(resetCtrlClockDomain) {
|
||||
val mainClkResetUnbuffered = False
|
||||
|
||||
//Implement an counter to keep the reset axiResetOrder high 64 cycles
|
||||
// Also this counter will automatically do a reset when the system boot.
|
||||
val systemClkResetCounter = Reg(UInt(6 bits)) init(0)
|
||||
when(systemClkResetCounter =/= U(systemClkResetCounter.range -> true)){
|
||||
systemClkResetCounter := systemClkResetCounter + 1
|
||||
mainClkResetUnbuffered := True
|
||||
}
|
||||
when(BufferCC(io.asyncReset)){
|
||||
systemClkResetCounter := 0
|
||||
}
|
||||
|
||||
//Create all reset used later in the design
|
||||
val mainClkReset = RegNext(mainClkResetUnbuffered)
|
||||
val systemReset = RegNext(mainClkResetUnbuffered)
|
||||
}
|
||||
|
||||
|
||||
val systemClockDomain = ClockDomain(
|
||||
clock = io.mainClk,
|
||||
reset = resetCtrl.systemReset,
|
||||
frequency = FixedFrequency(coreFrequency)
|
||||
)
|
||||
|
||||
val debugClockDomain = ClockDomain(
|
||||
clock = io.mainClk,
|
||||
reset = resetCtrl.mainClkReset,
|
||||
frequency = FixedFrequency(coreFrequency)
|
||||
)
|
||||
|
||||
val system = new ClockingArea(systemClockDomain) {
|
||||
val pipelinedMemoryBusConfig = PipelinedMemoryBusConfig(
|
||||
addressWidth = 32,
|
||||
dataWidth = 32
|
||||
)
|
||||
|
||||
val bigEndianDBus = config.cpuPlugins.exists(_ match{ case plugin : DBusSimplePlugin => plugin.bigEndian case _ => false})
|
||||
|
||||
//Arbiter of the cpu dBus/iBus to drive the mainBus
|
||||
//Priority to dBus, !! cmd transactions can change on the fly !!
|
||||
val mainBusArbiter = new MuraxMasterArbiter(pipelinedMemoryBusConfig, bigEndianDBus)
|
||||
|
||||
//Instanciate the CPU
|
||||
val cpu = new VexRiscv(
|
||||
config = VexRiscvConfig(
|
||||
plugins = cpuPlugins += new DebugPlugin(debugClockDomain, hardwareBreakpointCount)
|
||||
)
|
||||
)
|
||||
|
||||
//Checkout plugins used to instanciate the CPU to connect them to the SoC
|
||||
val timerInterrupt = False
|
||||
val externalInterrupt = False
|
||||
for(plugin <- cpu.plugins) plugin match{
|
||||
case plugin : IBusSimplePlugin =>
|
||||
mainBusArbiter.io.iBus.cmd <> plugin.iBus.cmd
|
||||
mainBusArbiter.io.iBus.rsp <> plugin.iBus.rsp
|
||||
case plugin : DBusSimplePlugin => {
|
||||
if(!pipelineDBus)
|
||||
mainBusArbiter.io.dBus <> plugin.dBus
|
||||
else {
|
||||
mainBusArbiter.io.dBus.cmd << plugin.dBus.cmd.halfPipe()
|
||||
mainBusArbiter.io.dBus.rsp <> plugin.dBus.rsp
|
||||
}
|
||||
}
|
||||
case plugin : CsrPlugin => {
|
||||
plugin.externalInterrupt := externalInterrupt
|
||||
plugin.timerInterrupt := timerInterrupt
|
||||
}
|
||||
case plugin : DebugPlugin => plugin.debugClockDomain{
|
||||
resetCtrl.systemReset setWhen(RegNext(plugin.io.resetOut))
|
||||
io.jtag <> plugin.io.bus.fromJtag()
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
|
||||
|
||||
|
||||
//****** MainBus slaves ********
|
||||
val mainBusMapping = ArrayBuffer[(PipelinedMemoryBus,SizeMapping)]()
|
||||
val ram = new MuraxPipelinedMemoryBusRam(
|
||||
onChipRamSize = onChipRamSize,
|
||||
onChipRamHexFile = onChipRamHexFile,
|
||||
pipelinedMemoryBusConfig = pipelinedMemoryBusConfig,
|
||||
bigEndian = bigEndianDBus
|
||||
)
|
||||
mainBusMapping += ram.io.bus -> (0x00000000l, onChipRamSize)
|
||||
|
||||
val apbBridge = new PipelinedMemoryBusToApbBridge(
|
||||
apb3Config = Apb3Config(
|
||||
addressWidth = 20,
|
||||
dataWidth = 32
|
||||
),
|
||||
pipelineBridge = pipelineApbBridge,
|
||||
pipelinedMemoryBusConfig = pipelinedMemoryBusConfig
|
||||
)
|
||||
mainBusMapping += apbBridge.io.pipelinedMemoryBus -> (0xF0000000l, 1 MB)
|
||||
|
||||
|
||||
|
||||
//******** APB peripherals *********
|
||||
val apbMapping = ArrayBuffer[(Apb3, SizeMapping)]()
|
||||
val gpioACtrl = Apb3Gpio(gpioWidth = gpioWidth, withReadSync = true)
|
||||
io.gpioA <> gpioACtrl.io.gpio
|
||||
apbMapping += gpioACtrl.io.apb -> (0x00000, 4 kB)
|
||||
|
||||
val uartCtrl = Apb3UartCtrl(uartCtrlConfig)
|
||||
uartCtrl.io.uart <> io.uart
|
||||
externalInterrupt setWhen(uartCtrl.io.interrupt)
|
||||
apbMapping += uartCtrl.io.apb -> (0x10000, 4 kB)
|
||||
|
||||
val timer = new MuraxApb3Timer()
|
||||
timerInterrupt setWhen(timer.io.interrupt)
|
||||
apbMapping += timer.io.apb -> (0x20000, 4 kB)
|
||||
|
||||
val xip = ifGen(genXip)(new Area{
|
||||
val ctrl = Apb3SpiXdrMasterCtrl(xipConfig)
|
||||
ctrl.io.spi <> io.xip
|
||||
externalInterrupt setWhen(ctrl.io.interrupt)
|
||||
apbMapping += ctrl.io.apb -> (0x1F000, 4 kB)
|
||||
|
||||
val accessBus = new PipelinedMemoryBus(PipelinedMemoryBusConfig(24,32))
|
||||
mainBusMapping += accessBus -> (0xE0000000l, 16 MB)
|
||||
|
||||
ctrl.io.xip.fromPipelinedMemoryBus() << accessBus
|
||||
val bootloader = Apb3Rom("src/main/c/murax/xipBootloader/crt.bin")
|
||||
apbMapping += bootloader.io.apb -> (0x1E000, 4 kB)
|
||||
})
|
||||
|
||||
|
||||
|
||||
//******** Memory mappings *********
|
||||
val apbDecoder = Apb3Decoder(
|
||||
master = apbBridge.io.apb,
|
||||
slaves = apbMapping.toSeq
|
||||
)
|
||||
|
||||
val mainBusDecoder = new Area {
|
||||
val logic = new MuraxPipelinedMemoryBusDecoder(
|
||||
master = mainBusArbiter.io.masterBus,
|
||||
specification = mainBusMapping.toSeq,
|
||||
pipelineMaster = pipelineMainBus
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
object Murax{
|
||||
def main(args: Array[String]) {
|
||||
SpinalVerilog(Murax(MuraxConfig.default))
|
||||
}
|
||||
}
|
||||
|
||||
object MuraxCfu{
|
||||
def main(args: Array[String]) {
|
||||
SpinalVerilog{
|
||||
val config = MuraxConfig.default
|
||||
config.cpuPlugins += new CfuPlugin(
|
||||
stageCount = 1,
|
||||
allowZeroLatency = true,
|
||||
encodings = List(
|
||||
CfuPluginEncoding (
|
||||
instruction = M"-------------------------0001011",
|
||||
functionId = List(14 downto 12),
|
||||
input2Kind = CfuPlugin.Input2Kind.RS
|
||||
)
|
||||
),
|
||||
busParameter = CfuBusParameter(
|
||||
CFU_VERSION = 0,
|
||||
CFU_INTERFACE_ID_W = 0,
|
||||
CFU_FUNCTION_ID_W = 3,
|
||||
CFU_REORDER_ID_W = 0,
|
||||
CFU_REQ_RESP_ID_W = 0,
|
||||
CFU_INPUTS = 2,
|
||||
CFU_INPUT_DATA_W = 32,
|
||||
CFU_OUTPUTS = 1,
|
||||
CFU_OUTPUT_DATA_W = 32,
|
||||
CFU_FLOW_REQ_READY_ALWAYS = false,
|
||||
CFU_FLOW_RESP_READY_ALWAYS = false,
|
||||
CFU_WITH_STATUS = true,
|
||||
CFU_RAW_INSN_W = 32,
|
||||
CFU_CFU_ID_W = 4,
|
||||
CFU_STATE_INDEX_NUM = 5
|
||||
)
|
||||
)
|
||||
|
||||
val toplevel = Murax(config)
|
||||
|
||||
toplevel.rework {
|
||||
for (plugin <- toplevel.system.cpu.plugins) plugin match {
|
||||
case plugin: CfuPlugin => plugin.bus.toIo().setName("miaou")
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
|
||||
toplevel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
object Murax_iCE40_hx8k_breakout_board_xip{
|
||||
|
||||
case class SB_GB() extends BlackBox{
|
||||
val USER_SIGNAL_TO_GLOBAL_BUFFER = in Bool()
|
||||
val GLOBAL_BUFFER_OUTPUT = out Bool()
|
||||
}
|
||||
|
||||
case class SB_IO_SCLK() extends BlackBox{
|
||||
addGeneric("PIN_TYPE", B"010000")
|
||||
val PACKAGE_PIN = out Bool()
|
||||
val OUTPUT_CLK = in Bool()
|
||||
val CLOCK_ENABLE = in Bool()
|
||||
val D_OUT_0 = in Bool()
|
||||
val D_OUT_1 = in Bool()
|
||||
setDefinitionName("SB_IO")
|
||||
}
|
||||
|
||||
case class SB_IO_DATA() extends BlackBox{
|
||||
addGeneric("PIN_TYPE", B"110000")
|
||||
val PACKAGE_PIN = inout(Analog(Bool))
|
||||
val CLOCK_ENABLE = in Bool()
|
||||
val INPUT_CLK = in Bool()
|
||||
val OUTPUT_CLK = in Bool()
|
||||
val OUTPUT_ENABLE = in Bool()
|
||||
val D_OUT_0 = in Bool()
|
||||
val D_OUT_1 = in Bool()
|
||||
val D_IN_0 = out Bool()
|
||||
val D_IN_1 = out Bool()
|
||||
setDefinitionName("SB_IO")
|
||||
}
|
||||
|
||||
case class Murax_iCE40_hx8k_breakout_board_xip() extends Component{
|
||||
val io = new Bundle {
|
||||
val mainClk = in Bool()
|
||||
val jtag_tck = in Bool()
|
||||
val jtag_tdi = in Bool()
|
||||
val jtag_tdo = out Bool()
|
||||
val jtag_tms = in Bool()
|
||||
val uart_txd = out Bool()
|
||||
val uart_rxd = in Bool()
|
||||
|
||||
val mosi = inout(Analog(Bool))
|
||||
val miso = inout(Analog(Bool))
|
||||
val sclk = out Bool()
|
||||
val spis = out Bool()
|
||||
|
||||
val led = out Bits(8 bits)
|
||||
}
|
||||
val murax = Murax(MuraxConfig.default(withXip = true).copy(onChipRamSize = 8 kB))
|
||||
murax.io.asyncReset := False
|
||||
|
||||
val mainClkBuffer = SB_GB()
|
||||
mainClkBuffer.USER_SIGNAL_TO_GLOBAL_BUFFER <> io.mainClk
|
||||
mainClkBuffer.GLOBAL_BUFFER_OUTPUT <> murax.io.mainClk
|
||||
|
||||
val jtagClkBuffer = SB_GB()
|
||||
jtagClkBuffer.USER_SIGNAL_TO_GLOBAL_BUFFER <> io.jtag_tck
|
||||
jtagClkBuffer.GLOBAL_BUFFER_OUTPUT <> murax.io.jtag.tck
|
||||
|
||||
io.led <> murax.io.gpioA.write(7 downto 0)
|
||||
|
||||
murax.io.jtag.tdi <> io.jtag_tdi
|
||||
murax.io.jtag.tdo <> io.jtag_tdo
|
||||
murax.io.jtag.tms <> io.jtag_tms
|
||||
murax.io.gpioA.read <> 0
|
||||
murax.io.uart.txd <> io.uart_txd
|
||||
murax.io.uart.rxd <> io.uart_rxd
|
||||
|
||||
|
||||
|
||||
val xip = new ClockingArea(murax.systemClockDomain) {
|
||||
RegNext(murax.io.xip.ss.asBool) <> io.spis
|
||||
|
||||
val sclkIo = SB_IO_SCLK()
|
||||
sclkIo.PACKAGE_PIN <> io.sclk
|
||||
sclkIo.CLOCK_ENABLE := True
|
||||
|
||||
sclkIo.OUTPUT_CLK := ClockDomain.current.readClockWire
|
||||
sclkIo.D_OUT_0 <> murax.io.xip.sclk.write(0)
|
||||
sclkIo.D_OUT_1 <> RegNext(murax.io.xip.sclk.write(1))
|
||||
|
||||
val datas = for ((data, pin) <- (murax.io.xip.data, List(io.mosi, io.miso)).zipped) yield new Area {
|
||||
val dataIo = SB_IO_DATA()
|
||||
dataIo.PACKAGE_PIN := pin
|
||||
dataIo.CLOCK_ENABLE := True
|
||||
|
||||
dataIo.OUTPUT_CLK := ClockDomain.current.readClockWire
|
||||
dataIo.OUTPUT_ENABLE <> data.writeEnable
|
||||
dataIo.D_OUT_0 <> data.write(0)
|
||||
dataIo.D_OUT_1 <> RegNext(data.write(1))
|
||||
|
||||
dataIo.INPUT_CLK := ClockDomain.current.readClockWire
|
||||
data.read(0) := dataIo.D_IN_0
|
||||
data.read(1) := RegNext(dataIo.D_IN_1)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
def main(args: Array[String]) {
|
||||
SpinalVerilog(Murax_iCE40_hx8k_breakout_board_xip())
|
||||
}
|
||||
}
|
||||
|
||||
object MuraxDhrystoneReady{
|
||||
def main(args: Array[String]) {
|
||||
SpinalVerilog(Murax(MuraxConfig.fast.copy(onChipRamSize = 256 kB)))
|
||||
}
|
||||
}
|
||||
|
||||
object MuraxDhrystoneReadyMulDivStatic{
|
||||
def main(args: Array[String]) {
|
||||
SpinalVerilog({
|
||||
val config = MuraxConfig.fast.copy(onChipRamSize = 256 kB)
|
||||
config.cpuPlugins += new MulPlugin
|
||||
config.cpuPlugins += new DivPlugin
|
||||
config.cpuPlugins.remove(config.cpuPlugins.indexWhere(_.isInstanceOf[BranchPlugin]))
|
||||
config.cpuPlugins +=new BranchPlugin(
|
||||
earlyBranch = false,
|
||||
catchAddressMisaligned = false
|
||||
)
|
||||
config.cpuPlugins += new IBusSimplePlugin(
|
||||
resetVector = 0x00000000l,
|
||||
cmdForkOnSecondStage = true,
|
||||
cmdForkPersistence = false,
|
||||
prediction = STATIC,
|
||||
catchAccessFault = false,
|
||||
compressedGen = false
|
||||
)
|
||||
config.cpuPlugins.remove(config.cpuPlugins.indexWhere(_.isInstanceOf[LightShifterPlugin]))
|
||||
config.cpuPlugins += new FullBarrelShifterPlugin
|
||||
Murax(config)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
//Will blink led and echo UART RX to UART TX (in the verilator sim, type some text and press enter to send UART frame to the Murax RX pin)
|
||||
object MuraxWithRamInit{
|
||||
def main(args: Array[String]) {
|
||||
SpinalVerilog(Murax(MuraxConfig.default.copy(onChipRamSize = 4 kB, onChipRamHexFile = "src/main/ressource/hex/muraxDemo.hex")))
|
||||
}
|
||||
}
|
||||
|
||||
object Murax_arty{
|
||||
def main(args: Array[String]) {
|
||||
val hex = "src/main/c/murax/hello_world/build/hello_world.hex"
|
||||
SpinalVerilog(Murax(MuraxConfig.default(false).copy(coreFrequency = 100 MHz,onChipRamSize = 32 kB, onChipRamHexFile = hex)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
object MuraxAsicBlackBox extends App{
|
||||
println("Warning this soc do not has any rom to boot on.")
|
||||
val config = SpinalConfig()
|
||||
config.addStandardMemBlackboxing(blackboxAll)
|
||||
config.generateVerilog(Murax(MuraxConfig.default()))
|
||||
}
|
||||
|
|
@ -9,12 +9,13 @@ _start:
|
|||
la gp, __global_pointer$
|
||||
.option pop
|
||||
|
||||
li sp, 0x800ffff0
|
||||
li sp, 0x1fff0
|
||||
|
||||
# Clear the bss segment
|
||||
la a0, __bss_start
|
||||
la a1, __BSS_END__
|
||||
|
||||
j finish_bss
|
||||
clear_bss:
|
||||
bgeu a0, a1, finish_bss
|
||||
sb x0, 0(a0)
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
.text
|
||||
.global _start
|
||||
.type _start, @function
|
||||
|
||||
_start:
|
||||
# Initialize global pointer
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, __global_pointer$
|
||||
.option pop
|
||||
|
||||
li sp, 0x1fff0
|
||||
|
||||
# Clear the bss segment
|
||||
la a0, __bss_start
|
||||
la a1, __BSS_END__
|
||||
|
||||
clear_bss:
|
||||
bgeu a0, a1, finish_bss
|
||||
sb x0, 0(a0)
|
||||
addi a0, a0, 1
|
||||
beq x0, x0, clear_bss
|
||||
finish_bss:
|
||||
|
||||
nop //!
|
||||
|
||||
call main
|
||||
|
||||
nop //!
|
||||
|
||||
# abort execution here
|
||||
ebreak
|
||||
|
||||
.section .rodata
|
||||
alfabet:
|
||||
.string "abcdefghijklmnopqrstuwxyz"
|
||||
slowo:
|
||||
|
||||
.section .data
|
||||
wynik:
|
||||
.string "mpabi"
|
||||
.space 26 # rezerwuje 26 bajtów dla wyniku, zainicjowane na 0
|
|
@ -1,39 +0,0 @@
|
|||
.text
|
||||
.global _start
|
||||
.type _start, @function
|
||||
|
||||
_start:
|
||||
# Initialize global pointer
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, __global_pointer$
|
||||
.option pop
|
||||
|
||||
# Initialize stack pointer from linker script symbol
|
||||
la sp, __stack_top
|
||||
|
||||
# Clear the BSS segment
|
||||
la a0, __bss_start
|
||||
la a1, __bss_end
|
||||
|
||||
clear_bss:
|
||||
bgeu a0, a1, finish_bss
|
||||
sb x0, 0(a0)
|
||||
addi a0, a0, 1
|
||||
j clear_bss
|
||||
finish_bss:
|
||||
|
||||
call main
|
||||
|
||||
ebreak
|
||||
|
||||
.section .rodata
|
||||
|
||||
alfabet:
|
||||
.string "abcdefghijklmnopqrstuwxyz"
|
||||
slowo:
|
||||
|
||||
.section .data
|
||||
wynik:
|
||||
.string "mpabi"
|
||||
.space 26 # rezerwuje 26 bajtów dla wyniku, zainicjowane na 0
|
|
@ -0,0 +1 @@
|
|||
riscv64-unknown-elf-objdump -S --disassemble prog > prog.dis
|
|
@ -0,0 +1 @@
|
|||
readelf -S -W prog
|
|
@ -7,7 +7,6 @@ int strlen(char *s) {
|
|||
return p - s;
|
||||
}
|
||||
|
||||
|
||||
void strcpy(char *s, char *t)
|
||||
{
|
||||
while (*s++ = *t++);
|
||||
|
@ -66,13 +65,14 @@ char *simple_strtok(char *str, const char *delims) {
|
|||
static char *static_str = (char *) NULL; // Przechowuje wskaźnik do bieżącej pozycji w ciągu
|
||||
|
||||
// Jeśli przekazano nowy ciąg, zaktualizuj static_str
|
||||
if (str == NULL) {
|
||||
return (char *) NULL; // str nie wskazuje na zdanie !!!
|
||||
}
|
||||
if (str != NULL) {
|
||||
static_str = str;
|
||||
}
|
||||
|
||||
// " .,mpabi"
|
||||
// ^
|
||||
// Jeśli static_str jest NULL, zwróć NULL
|
||||
if (static_str == NULL) {
|
||||
return (char *) NULL;
|
||||
}
|
||||
|
||||
// Pomiń początkowe delimitery
|
||||
while (*static_str && is_delim(*static_str, delims)) {
|
||||
|
@ -102,40 +102,21 @@ char *simple_strtok(char *str, const char *delims) {
|
|||
return token_start;
|
||||
}
|
||||
|
||||
char buf[100];
|
||||
struct model * p = (struct model *) buf; //p[1]
|
||||
////func alg
|
||||
//in: ptr to date
|
||||
//return: count of words
|
||||
int alg (const char * ptr) {
|
||||
|
||||
char bufer[ALLOCSIZE];
|
||||
strcpy(bufer, (char *)ptr);
|
||||
|
||||
const char *delims = " ,.!?:;\n\t";
|
||||
|
||||
int8_t count = 0;
|
||||
|
||||
char *token = simple_strtok(bufer, delims);
|
||||
|
||||
while (token != (char *)NULL) {
|
||||
|
||||
p[count].str = token;
|
||||
p[count].len = strlen(token);
|
||||
|
||||
token = simple_strtok((char *)NULL, delims);
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
|
||||
char *str = "If wantered relation no surprise of all";
|
||||
|
||||
alg(str);
|
||||
asm ("nop");
|
||||
struct model * ptr = (struct model *) alloc (LEN);
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
# set args 0x1FF80 0x80 0x30
|
||||
# source gdb/z.py
|
||||
|
||||
import gdb
|
||||
import sys
|
||||
|
||||
# Parse arguments from the GDB command
|
||||
args = gdb.string_to_argv(gdb.parameter("args"))
|
||||
if len(args) != 3:
|
||||
print("Usage: source gdb/zero_with_params.py <start_address> <num_bytes> <pattern>")
|
||||
else:
|
||||
start_address = int(args[0], 16) # Convert start address from hex to int
|
||||
num_bytes = int(args[1], 16) # Convert number of bytes from hex to int
|
||||
pattern = int(args[2], 16) # Convert pattern from hex to int
|
||||
|
||||
for i in range(num_bytes):
|
||||
gdb.execute("set *((char*)%x + %x) = %x" % (start_address, i, pattern))
|
|
@ -0,0 +1,5 @@
|
|||
#source gdb/z.py
|
||||
|
||||
import gdb
|
||||
for i in range(0, 128): # 128 bajtów
|
||||
gdb.execute("set *((char*)(0x1FF80 + %x)) = 0xaa" % i)
|
|
@ -1,43 +0,0 @@
|
|||
MEMORY
|
||||
{
|
||||
RAM (wx) : ORIGIN = 0x0, LENGTH = 128K
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
*(.text*)
|
||||
*(.rodata*)
|
||||
} > RAM
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.data*)
|
||||
} > RAM
|
||||
|
||||
.bss :
|
||||
{
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
} > RAM
|
||||
|
||||
/* Add stack at the end of RAM */
|
||||
. = ALIGN(4);
|
||||
_end = .;
|
||||
PROVIDE(end = .);
|
||||
|
||||
/* Define stack size and location */
|
||||
_stack_size = 0x4000; /* Example stack size: 16KB */
|
||||
_stack_end = ORIGIN(RAM) + LENGTH(RAM); /* End of RAM */
|
||||
_stack_start = _stack_end - _stack_size; /* Calculate start of the stack */
|
||||
.stack (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
. = . + _stack_size;
|
||||
. = ALIGN(4);
|
||||
_sp = .;
|
||||
} > RAM
|
||||
|
||||
PROVIDE(__stack = _sp);
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
/* Linker script for a system with 128KB RAM starting at 0x10000 */
|
||||
MEMORY
|
||||
{
|
||||
RAM (wx) : ORIGIN = 0x0000, LENGTH = 128K
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* Place code and readonly data at the beginning of RAM */
|
||||
.text :
|
||||
{
|
||||
*(.text*)
|
||||
*(.rodata*)
|
||||
} > RAM
|
||||
|
||||
/* Place initialized data right after the .text section */
|
||||
.data :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.data*)
|
||||
} > RAM
|
||||
|
||||
/* Uninitialized data (BSS) follows initialized data */
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__bss_start = .;
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end = .;
|
||||
} > RAM
|
||||
|
||||
/* Define heap start right after bss */
|
||||
. = ALIGN(4);
|
||||
__heap_start = .;
|
||||
PROVIDE(heap_start = __heap_start);
|
||||
|
||||
/* Leave space for the heap by not explicitly defining its end */
|
||||
/* The heap grows towards the stack */
|
||||
|
||||
/* Reserve space for the stack at the end of RAM */
|
||||
/* Let's say we want a 16KB stack */
|
||||
. = ALIGN(4);
|
||||
__stack_size = 16K; /* Size of the stack */
|
||||
__stack_top = ORIGIN(RAM) + LENGTH(RAM); /* Top of the stack */
|
||||
__stack_start = __stack_top - __stack_size; /* Start of the stack */
|
||||
.stack (NOLOAD) :
|
||||
{
|
||||
. = __stack_start;
|
||||
. += __stack_size; /* Allocate space for the stack */
|
||||
. = ALIGN(4);
|
||||
} > RAM
|
||||
|
||||
PROVIDE(__stack = __stack_top);
|
||||
PROVIDE(stack_top = __stack_top);
|
||||
PROVIDE(stack_start = __stack_start);
|
||||
|
||||
/* Heap end is dynamically located at the start of the stack */
|
||||
__heap_end = __stack_start;
|
||||
PROVIDE(heap_end = __heap_end);
|
||||
|
||||
/* End of RAM usage */
|
||||
. = ALIGN(4);
|
||||
_end = .;
|
||||
PROVIDE(end = _end);
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
MEMORY
|
||||
{
|
||||
RAM (wx) : ORIGIN = 0x10000, LENGTH = 128K
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text : { *(.text*) } > RAM
|
||||
.rodata : { *(.rodata*) } > RAM
|
||||
.data : { *(.data*) } > RAM
|
||||
.bss : { *(.bss*) } > RAM
|
||||
_end = .; /* Definiuje koniec sekcji danych, może być używane do określenia rozmiaru sterty */
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
#include "myfuncOOP.hpp"
|
||||
|
||||
MyfuncOOP::MyfuncOOP(const char* alfabet, const char* slowo, uint8_t* wynik)
|
||||
: alfabet(alfabet), slowo(slowo), wynik(wynik) {
|
||||
}
|
||||
|
||||
void MyfuncOOP::countCharacters() {
|
||||
int alfabet_length = myStrlen(alfabet);
|
||||
|
||||
for (int i = 0; i < alfabet_length; ++i) {
|
||||
wynik[i] = 0; // Initialize counts to zero
|
||||
}
|
||||
|
||||
for (int i = 0; i < alfabet_length; ++i) {
|
||||
for (int j = 0; slowo[j] != '\0'; ++j) {
|
||||
if (alfabet[i] == slowo[j]) {
|
||||
wynik[i]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t* MyfuncOOP::getResults() const {
|
||||
return wynik;
|
||||
}
|
||||
|
||||
int MyfuncOOP::myStrlen(const char* str) {
|
||||
int length = 0;
|
||||
while (str[length] != '\0') {
|
||||
++length;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
// MyfuncOOP zliczacz(alfabet, slowo, wynik);
|
||||
// zliczacz.countCharacters();
|
||||
// const uint8_t* results = zliczacz.getResults();
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef MYFUNC_OOP_HPP
|
||||
#define MYFUNC_OOP_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class MyfuncOOP {
|
||||
public:
|
||||
MyfuncOOP(const char* alfabet, const char* slowo, uint8_t* wynik);
|
||||
|
||||
void countCharacters();
|
||||
|
||||
const uint8_t* getResults() const;
|
||||
|
||||
private:
|
||||
const char* alfabet;
|
||||
const char* slowo;
|
||||
uint8_t* wynik;
|
||||
|
||||
static int myStrlen(const char* str);
|
||||
};
|
||||
|
||||
#endif // MYFUNC_OOP_HPP
|
|
@ -0,0 +1,29 @@
|
|||
#include "myfuncStruct.h"
|
||||
|
||||
// Static function for string length calculation
|
||||
static int my_strlen(const char *str) {
|
||||
int length = 0;
|
||||
while (str[length] != '\0') {
|
||||
length++;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
// Function to count occurrences of each character in 'alfabet' within 'slowo'
|
||||
void count_charactersStruct(ZliczaczStruct* zliczacz) {
|
||||
int alfabet_length = my_strlen(zliczacz->alfabet);
|
||||
|
||||
// Initialize the result array to zero
|
||||
for (int i = 0; i < alfabet_length; ++i) {
|
||||
zliczacz->wynik[i] = 0;
|
||||
}
|
||||
|
||||
// Count occurrences
|
||||
for (int i = 0; i < alfabet_length; ++i) {
|
||||
for (int j = 0; zliczacz->slowo[j] != '\0'; ++j) {
|
||||
if (zliczacz->alfabet[i] == zliczacz->slowo[j]) {
|
||||
zliczacz->wynik[i]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef MYFUNCSTRUCT_H
|
||||
#define MYFUNCSTRUCT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
const char* alfabet;
|
||||
const char* slowo;
|
||||
uint8_t* wynik; // Pointer to an array for results
|
||||
} ZliczaczStruct;
|
||||
|
||||
// Function declaration for counting character occurrences
|
||||
void count_charactersStruct(ZliczaczStruct* zliczacz);
|
||||
|
||||
#endif // MYFUNCSTRUCT_H
|
|
@ -0,0 +1,44 @@
|
|||
#include "myfuncStructOOP.h"
|
||||
|
||||
// Static function for string length calculation
|
||||
static int my_strlen(const char *str) {
|
||||
int length = 0;
|
||||
while (str[length] != '\0') {
|
||||
length++;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
// 'Method' to count occurrences of each character
|
||||
static void count_charactersStructOOP(ZliczaczStructOOP* zliczacz) {
|
||||
int alfabet_length = my_strlen(zliczacz->alfabet);
|
||||
|
||||
// Initialize the result array to zero
|
||||
for (int i = 0; i < alfabet_length; ++i) {
|
||||
zliczacz->wynik[i] = 0;
|
||||
}
|
||||
|
||||
// Count occurrences
|
||||
for (int i = 0; i < alfabet_length; ++i) {
|
||||
for (int j = 0; zliczacz->slowo[j] != '\0'; ++j) {
|
||||
if (zliczacz->alfabet[i] == zliczacz->slowo[j]) {
|
||||
zliczacz->wynik[i]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Constructor-like function to initialize a ZliczaczStructOOP
|
||||
void initializeZliczaczStructOOP(ZliczaczStructOOP* zliczacz, const char* alfabet, const char* slowo, uint8_t* wynik) {
|
||||
zliczacz->alfabet = alfabet;
|
||||
zliczacz->slowo = slowo;
|
||||
zliczacz->wynik = wynik;
|
||||
zliczacz->count_characters = count_charactersStructOOP;
|
||||
}
|
||||
|
||||
// #include "myfuncStructOOP.h"
|
||||
|
||||
// ZliczaczStructOOP zliczacz;
|
||||
// initializeZliczaczStructOOP(&zliczacz, alfabet, slowo, wynik);
|
||||
|
||||
// zliczacz.count_characters(&zliczacz);
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef MYFUNCSTRUCTOOP_H
|
||||
#define MYFUNCSTRUCTOOP_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct ZliczaczStructOOP ZliczaczStructOOP;
|
||||
|
||||
struct ZliczaczStructOOP {
|
||||
// Data members
|
||||
const char* alfabet;
|
||||
const char* slowo;
|
||||
uint8_t* wynik; // Pointer to an array for results
|
||||
|
||||
// Function pointers, acting as 'methods'
|
||||
void (*count_characters)(ZliczaczStructOOP*);
|
||||
};
|
||||
|
||||
void initializeZliczaczStructOOP(ZliczaczStructOOP* zliczacz, const char* alfabet, const char* slowo, uint8_t* wynik);
|
||||
|
||||
|
||||
#endif // MYFUNCSTRUCTOOP_H
|
|
@ -0,0 +1,5 @@
|
|||
_crt0.S
|
||||
main.cpp
|
||||
myfunc.cpp
|
||||
myfunc.h
|
||||
_rvmain.cc
|
|
@ -0,0 +1,16 @@
|
|||
import asyncio
|
||||
import websockets
|
||||
|
||||
async def consume_ws_latest_records():
|
||||
uri = "ws://172.24.0.3:3333/ws_latest_records"
|
||||
|
||||
async with websockets.connect(uri) as websocket:
|
||||
while True:
|
||||
message = input("Enter a message to send: ")
|
||||
await websocket.send(message)
|
||||
|
||||
response = await websocket.recv()
|
||||
print(f"Received from server: {response}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.get_event_loop().run_until_complete(consume_ws_latest_records())
|
|
@ -0,0 +1 @@
|
|||
g++ -std=c++17 -o websocket-client-sync main.cpp myfunc.cpp -lboost_system -lboost_thread -lboost_coroutine -ljsoncpp
|
|
@ -0,0 +1 @@
|
|||
./websocket-client-sync ws://localhost:3333/ws
|
|
@ -0,0 +1,155 @@
|
|||
#include <boost/beast/core.hpp>
|
||||
#include <boost/beast/websocket.hpp>
|
||||
#include <boost/asio/connect.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <jsoncpp/json/json.h>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <regex>
|
||||
|
||||
namespace beast = boost::beast;
|
||||
namespace websocket = beast::websocket;
|
||||
namespace net = boost::asio;
|
||||
using tcp = boost::asio::ip::tcp;
|
||||
|
||||
struct Person {
|
||||
std::string name;
|
||||
int age;
|
||||
long long timestamp;
|
||||
};
|
||||
|
||||
Json::Value serializePerson(const Person& person) {
|
||||
Json::Value jsonPerson;
|
||||
jsonPerson["name"] = person.name;
|
||||
jsonPerson["age"] = person.age;
|
||||
jsonPerson["timestamp"] = static_cast<Json::Value::Int64>(person.timestamp);
|
||||
return jsonPerson;
|
||||
}
|
||||
|
||||
std::tuple<std::string, std::string, std::string> parseURI(const std::string& uri) {
|
||||
std::regex uriRegex(R"(^ws://([^:/]+):(\d+)(/.+)$)");
|
||||
std::smatch match;
|
||||
|
||||
if (std::regex_match(uri, match, uriRegex)) {
|
||||
return std::make_tuple(match[1].str(), match[2].str(), match[3].str());
|
||||
} else {
|
||||
throw std::invalid_argument("Nieprawidłowe URI");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T getInput(const std::string& prompt) {
|
||||
T value;
|
||||
while (true) {
|
||||
std::cout << prompt;
|
||||
std::cin >> value;
|
||||
|
||||
if (std::cin.fail()) {
|
||||
std::cin.clear();
|
||||
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||||
std::cerr << "Błąd! Spróbuj ponownie." << std::endl;
|
||||
} else {
|
||||
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void iterateCharBuffer(const char* charBuffer, std::size_t bufferSize) {
|
||||
for (std::size_t i = 0; i < bufferSize; ++i) {
|
||||
std::cout << charBuffer[i];
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
// Example: Call the function you want to apply to the char buffer
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
try {
|
||||
if (argc != 2) {
|
||||
std::cerr << "Sposób użycia: " << argv[0] << " <adres URI>\n";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
std::string uri = argv[1];
|
||||
auto uriParts = parseURI(uri);
|
||||
std::string host, port, endpoint;
|
||||
std::tie(host, port, endpoint) = uriParts;
|
||||
|
||||
net::io_context io_context;
|
||||
|
||||
websocket::stream<tcp::socket> ws(io_context);
|
||||
tcp::resolver resolver(io_context);
|
||||
auto endpoints = resolver.resolve(host, port);
|
||||
net::connect(ws.next_layer(), endpoints);
|
||||
|
||||
ws.handshake(host, endpoint);
|
||||
|
||||
while (true) {
|
||||
std::cout << "Menu:\n";
|
||||
std::cout << "1. Dodaj rekord\n";
|
||||
std::cout << "2. Zwróć ostatnie rekordy\n";
|
||||
std::cout << "3. Wyjście\n";
|
||||
|
||||
int choice = getInput<int>("Wybierz opcję: ");
|
||||
|
||||
if (choice == 1) {
|
||||
|
||||
std::string name = getInput<std::string>("Podaj imię: ");
|
||||
int age = getInput<int>("Podaj wiek: ");
|
||||
|
||||
Person personToSend{name, age, std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch()).count()};
|
||||
|
||||
Json::Value jsonPerson = serializePerson(personToSend);
|
||||
|
||||
ws.write(net::buffer(Json::writeString(Json::StreamWriterBuilder(), jsonPerson)));
|
||||
|
||||
} else if (choice == 2) {
|
||||
|
||||
ws.write(net::buffer("get_latest_records"));
|
||||
|
||||
beast::flat_buffer buffer;
|
||||
ws.read(buffer);
|
||||
|
||||
std::cout << "Otrzymano: " << beast::make_printable(buffer.data()) << std::endl;
|
||||
|
||||
const char* bufferData = boost::asio::buffer_cast<const char*>(buffer.data());
|
||||
std::size_t bufferSize = boost::asio::buffer_size(buffer.data());
|
||||
|
||||
char* charBuffer = new char[bufferSize + 1];
|
||||
std::memcpy(charBuffer, bufferData, bufferSize);
|
||||
charBuffer[bufferSize] = '\0';
|
||||
|
||||
iterateCharBuffer(charBuffer, bufferSize);
|
||||
|
||||
delete[] charBuffer;
|
||||
|
||||
buffer.consume(buffer.size());
|
||||
|
||||
} else if (choice == 3) {
|
||||
|
||||
std::cout << "Zamykanie programu...\n";
|
||||
break;
|
||||
|
||||
} else {
|
||||
|
||||
std::cout << "Nieprawidłowy wybór. Spróbuj ponownie.\n";
|
||||
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
}
|
||||
|
||||
} catch (std::exception const& e) {
|
||||
std::cerr << "Błąd: " << e.what() << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
#include <iostream>
|
||||
#include <tuple>
|
||||
#include <regex>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/beast.hpp>
|
||||
#include <jsoncpp/json/json.h>
|
||||
|
||||
namespace beast = boost::beast;
|
||||
namespace websocket = beast::websocket;
|
||||
namespace net = boost::asio;
|
||||
using tcp = boost::asio::ip::tcp;
|
||||
|
||||
std::tuple<std::string, std::string, std::string> parseURI(const std::string& uri) {
|
||||
std::regex uriRegex(R"(^ws://([^:/]+):(\d+)(/.+)$)");
|
||||
std::smatch match;
|
||||
|
||||
if (std::regex_match(uri, match, uriRegex)) {
|
||||
return std::make_tuple(match[1].str(), match[2].str(), match[3].str());
|
||||
} else {
|
||||
throw std::invalid_argument("Nieprawidłowe URI");
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::string uri = "ws://172.24.0.3:3333";
|
||||
std::cout << "Dostarczone URI: " << uri << std::endl;
|
||||
|
||||
try {
|
||||
auto uriParts = parseURI(uri);
|
||||
std::string host, port, endpoint;
|
||||
std::tie(host, port, endpoint) = uriParts;
|
||||
|
||||
net::io_context io_context;
|
||||
|
||||
// Utwórz obiekt WebSocket
|
||||
websocket::stream<tcp::socket> ws(io_context);
|
||||
|
||||
// Połącz z serwerem WebSocket
|
||||
tcp::resolver resolver(io_context);
|
||||
auto endpoints = resolver.resolve(host, port);
|
||||
net::connect(ws.next_layer(), endpoints);
|
||||
|
||||
// Wysyłanie danych na serwer WebSocket
|
||||
ws.handshake(host, endpoint);
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "Błąd: " << e.what() << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Loading…
Reference in New Issue