How do I connect a client to an IdentityNode with two managers? - chisel

The PCIe overlay I'm attempting to invoke connects the two slave/manager nodes to a slaveSide IdentityNode like so:
val slaveSide = TLIdentityNode()
pcie.crossTLIn(pcie.slave) := slaveSide
pcie.crossTLIn(pcie.control) := slaveSide
How do I connect my client to both of these nodes? Would it be something like this?
slaveSide :*= myClient
What if I wanted one client for each manager? Is there a way outside of changing the overlay placing function?

Something like the following worked for this situation.
// Assuming TLClient1 and TLClient2 have been declared.
val connectorNode = TLIdentityNode()
connectorNode := TLClient1
connectorNode := TLClient2
slaveSide :=* connectorNode
Since here the number of slaves and clients is equal
slaveSide :*= connectorNode
should be equally as valid.

Related

What are these `a.bits.user.amba_prot` signals and why are they only uninitialized conditionally in my HarnessBinder?

Context: I began using Chipyard about a month back to facilitate the building of a quick prototype using RISC-V cores on the VCU118. Chipyard was perfect, but required me to step up and learn Chisel and Rocket-chip tools to extend interconnection to my design.
The first piece of hardware to hook up was the PCIe to AXI Bridge IP provided by Xilinx known as XDMA. fpga-shells provides a wrapper, shell, and overlay for this IP already, so with some studying of the Chipyard System, HarnessBinders, and IOBinders, I managed to hook it up. The overlay was placed like so:
val overlayOutput = dp(PCIeOverlayKey).last.place(PCIeDesignInput(wrangler=dutWrangler.node, corePLL=harnessSysPLL)).overlayOutput
val (pcieNode: TLNode, pcieIntNode: IntOutwardNode) = (overlayOutput.pcieNode, overlayOutput.intNode)
val (pcieSlaveTLNode: TLIdentityNode, pcieMasterTLNode: TLAsyncSinkNode) = (pcieNode.inward, pcieNode.outward)
There are two slaves, but I'll only show the IOBinders and HarnessBinders for one. I'm assuming my other Port mixin is functioning correctly since it's exactly like the CanHaveMasterTLMMIO port, but with a separate key and different address ranges. I realize this is inefficient, but was easier than creating an external bus. Here is the IOBinder which takes advantage of CanHaveMasterTLMMIOPort to introduce a master MMIO port to the system bus.
class WithXDMASlaveIOPassthrough extends OverrideIOBinder({
(system: CanHaveMasterTLMMIOPort) => {
val io_xdma_slave_pins_temp = IO(DataMirror.internal.chiselTypeClone[HeterogeneousBag[TLBundle]](system.mmio_tl)).suggestName("tl_slave_mmio")
io_xdma_slave_pins_temp <> system.mmio_tl
(Seq(io_xdma_slave_pins_temp), Nil)
}
})
I retrieve and connect the slave nodes in the TestHarness like so:
val inParamsMMIOPeriph = topDesign match { case td: ChipTop =>
td.lazySystem match { case lsys: CanHaveMasterTLMMIOPort =>
lsys.mmioTLNode.edges.in(0)
}
}
val inParamsControl = topDesign match {case td: ChipTop =>
td.lazySystem match { case lsys: CanHaveMasterTLCtrlPort =>
lsys.ctrlTLNode.edges.in(0)
}
}
val pcieClient = TLClientNode(Seq(inParamsMMIOPeriph.master))
val pcieCtrlClient = TLClientNode(Seq(inParamsControl.master))
val connectorNode = TLIdentityNode()
// pcieSlaveTLNode should be driven for both the control slave and the axi bridge slave
connectorNode := pcieClient
connectorNode := pcieCtrlClient
pcieSlaveTLNode :=* connectorNode
Finally, I connect the node to a harness binder. I followed the way DDR was connected in Chipyard for this step.
class WithPCIeClient extends OverrideHarnessBinder({
(system: CanHaveMasterTLMMIOPort, th: BaseModule with HasHarnessSignalReferences, ports: Seq[HeterogeneousBag[TLBundle]]) => {
require(ports.size == 1)
th match { case vcu118th: FCMVCU118FPGATestHarnessImp => {
val bundles = vcu118th.fcmOuter.pcieClient.out.map(_._1)
val pcieClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType)))
pcieClientBundle <> DontCare // Some signals aren't being driven to this bundle, but it's hard to know how critical that is. Only happens when myPeripheral is on.
bundles.zip(pcieClientBundle).foreach{case (bundle, io) => bundle <> io}
pcieClientBundle <> ports.head
} }
}
})
I added the pcieClientBundle <> DontCare to surpress these undriven signals. This problem only affects the signals driven to both slaves.
Signals such as:
a.bits.user.amba_prot.fetch
a.bits.user.amba_prot.secure
a.bits.user.amba_prot.modifiable
a.bits.user.amba_prot.privileged
are undriven (resulting in a $RefNotInitializedException in FIRRTL pass through)
in both wires. I recognize these come from TLToAXI4 but what's weird is that they are only undriven when I connect another peripheral to the bus. This peripheral does not leave ChipTop. It has three master AXI buses connected to the system like so:
( peirpheralMasterNode1
:= TLBuffer(BufferParams.default)
:= TLWidthWidget(8)
:= AXI4ToTL()
:= AXI4UserYanker(capMaxFlight=Some(16))
:= AXI4Fragmenter()
:= AXI4IdIndexer(idBits=3)
:= AXI4Buffer()
:= peripheralTop.Master1)
fbus.fromPort(Some("PERIPHERAL_MASTER_1"))() := peripheralMasterNode1
The peripheral's AXI Lite slave is where I suspect the problem could be. Its node is declared like so:
val regCfgSlv = AXI4SlaveNode(Seq(AXI4SlavePortParameters(
slaves = Seq(AXI4SlaveParameters(
address = AddressSet.misaligned(0xf000E0000L, 0x1000L),
resources = regCfgDevice.reg("config"),
// executable = true, // Determines whether processor can execute from this memory.
supportsWrite = TransferSizes(1, 4),
supportsRead = TransferSizes(1, 4),
interleavedId = Some(0))),
beatBytes = 4
)))
And it is connected to the system bus using toSlave
sbus.toSlave(Some(portName)){
(peripheralTop.regCfgSlv
:= AXI4Buffer()
:= AXI4UserYanker(capMaxFlight=Some(2))
:= TLToAXI4()
// := TLWidthWidget(sbus.beatBytes))
:= TLFragmenter(4,
p(CacheBlockBytes),
// sbus.beatBytes,
holdFirstDeny = true)
:= TLWidthWidget(sbus.beatBytes))
}
When I include this mixin peripheral in my config by setting myPeripheral's key, I get the error about a.bits.user.amba_prot signals not being driven for both HarnessBinders Client Bundles [val pcieClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType)))]. When I only use one of myPeripheral or XDMA, the $RefNotInitializedException goes away.
Here are my configs. I have tried moving WithMyPeripheral around to no avail.
class CustomRocketConfig extends Config(
new WithPCIeMMIOPort ++ // add default external master port
new WithControlPort ++ // add control port for pcie cfg. // TODO: Crossbar this on MMIO Port? Move both MMIO and Control to a port on System Bus?
new freechips.rocketchip.subsystem.WithDefaultSlavePort ++ // add default external slave port
new WithMyPeripheral(MyPeripheralParams()) ++ // Link up myPeripheral
new freechips.rocketchip.subsystem.WithNBigCores(2) ++
new freechips.rocketchip.subsystem.WithNExtTopInterrupts(3) ++
new chipyard.config.AbstractConfig)
class WithPCIeTweaks extends Config (
new WithPCIeClient ++
new WithPCIeManager ++
new WithPCIeCtrlClient ++ // Same for these harness binders - ME
new WithXDMAMasterIOPassthrough ++
new WithXDMASlaveIOPassthrough ++
new WithXDMACtrlIOPassthrough // I imagine these three IOBinders can be combined into one - ME
//TODO: Probably need harness binder and io binder for interrupt if we use it
)
class myRocketConfig extends Config (
// new WithMyPeripheral(MyPeripheralParams()) ++ // Link up myPeripheral
new WithPCIeTweaks ++
new WithVCU118Tweaks ++
new WithMyVCU118System ++
new CustomRocketConfig
)
I hope my problem is clear and interesting. What are a.user.amba_prot signals and why are they undriven when I hook up both XDMA and my peripheral? Why is it that I can declare either myPeripheral or the XDMA, but, when I hook up both, these signals don't have drivers? I realize this is a difficult question with a lot of moving parts in an already scarcely viewed tag. If you took the time to read this and have suggestions, your kindness and expertise are greatly appreciated.
Edit: I think the issue might be parameter negotiation failing between Test Harness's diplomacy region and ChipTop's diplomacy region.
This is the control node in XDMA.
val control = AXI4SlaveNode(Seq(AXI4SlavePortParameters(
slaves = Seq(AXI4SlaveParameters(
address = List(AddressSet(c.control, c.ecamMask)),
resources = device.reg("control"),
supportsWrite = TransferSizes(1, 4),
supportsRead = TransferSizes(1, 4),
interleavedId = Some(0))), // AXI4-Lite never interleaves responses
beatBytes = 4)))
This is the port the system sees.
val mmioTLNode = TLManagerNode(
mmioPortParamsOpt.map(params =>
TLSlavePortParameters.v1(
managers = Seq(TLSlaveParameters.v1(
address = AddressSet.misaligned(params.base, params.size),
resources = device.ranges,
executable = params.executable,
supportsGet = TransferSizes(1, sbus.blockBytes),
supportsPutFull = TransferSizes(1, sbus.blockBytes),
supportsPutPartial = TransferSizes(1, sbus.blockBytes))),
beatBytes = params.beatBytes)).toSeq)
mmioPortParamsOpt.map { params =>
sbus.coupleTo(s"port_named_$portName") {
(mmioTLNode
:= TLBuffer()
:= TLSourceShrinker(1 << params.idBits)
:= TLWidthWidget(sbus.beatBytes)
:= _ )
}
}
param.beatBytes is currently set to 8 (site(MemoryBusKey).beatBytes). But the control configuration slave node is 4.
I have determined a somewhat satisfactory way around this error. My understanding of diplomacy might be flawed here, so if this helps someone craft a better answer, I'd love to hear it.
What are a.user.amba_prot signals?
These signals are a result of bridging protocols between TL and AXI4. If the master is originally AXI4, then it has ar and aw channel signals labelled prot and cache.
AxCACHE[0], Bufferable (B) bit
AxCACHE[1], Cacheable (C) bit (this is the "modifiable" bit)
AxCACHE[2], Read-allocate (RA) bit
AxCACHE[3], Write-allocate (WA) bit
AxPROT[0], Privileged Access bit
AxPROT[1], Secure Access bit
AxPROT[2], Data/Instruction Access bit
These signals are driven from AXI masters to AXI slaves.
Why is it that I can declare either myPeripheral or the XDMA, but, when I hook up both, these signals don't have drivers?
It's important to keep in mind the following point when using Chipyard: the Chipyard system is one diplomatic region. The Test Harness is another. So from Chipyard system perspective, XDMA appears completely as TL connections. It has a TL master driving its slave port and a TL slave on its master port. This is because XDMA in the PCIeOverlay uses Diplomacy to connect the AXI nodes to TileLink within the Test Harness diplomatic region. The system's diplomatic region can only see these TileLink master and slave ports. When AXI masters and slaves are connected, the TileLink client bundles now need amba_prot signals because the system can see it needs to connect to AXI slaves.
The workaround for this is to expose the AXI ports directly for XDMA. This way the system can see the AXI slaves and masters from XDMA and the bridge to TL can happen on the system side.

Delphi - DataSet creating too many connections in MySQL

I am having a problem using the TFDDataSet component in my application.
I have a function that fetch many times if a customer has new orders. If it returns empty the function ends.
...
fdm_XMLREsumo.Close;
fdm_XMLREsumo.Active := false;
_DataSetJSON := SM.GetXMLResumoChave( pEnt_ID, pChave); //See Edit 1
_DataSet.Close;
_DataSet := TFDJSONDataSetsReader.GetListValueByName( _DataSetJSON, sXMLResumo );
_DataSet.Open; <-- here's the problem
if not _DataSet.IsEmpty then begin
exit;
end;
fdm_XMLREsumo.AppendData( _DataSet );
...
The problem is every time it executes _DataSet.Open; it creates a new connection in my DB.Because of that I'm having a too many connections exception.I've checked in my Server Properties and it is like this:
I have tried Connection.Close,_DataSet.Close, _DataSet.Free and _DataSet.Destroy but nothing worked.I read this, and it explains that even if you do _DataSet.Close the connection still exists, because DataSets work in memory.There is also this guy having a similar issue, but using Query. Does anyone know how can I manage to solve this?I am using MySQL
EDIT 1
As #CraigYoung helped me saying my example needs MCVE
SM.GetXMLResumoChave method:
Here it uses a connection to the database that is closed at the end of the function. Already debugged, and here it does not leave an open connection in MySQL Proccess List
function TDAOXMLResumo.GetXMLResumoChave(xEnt_id: Integer; xChave: String): TFDJSONDataSets;
begin
if not oSM.FDConn.Connected then
oSM.FDConn.Connected := true;
QueryPesquisa.SQL.Clear;
QueryPesquisa.SQL.Text :=
' select * from table' +
' where ent_id = :ent_id ' +
' and xre_chNFe = :xre_chNFe ';
QueryPesquisa.ParamByName('ent_id').Asinteger := xEnt_id;
QueryPesquisa.ParamByName('xre_chNFe').Asstring := xChave;
Result := TFDJSONDataSets.Create;
//TFDJSONDataSetsWriter.ListAdd Opens the Query that is passed as parameter and store the data as JSON in the TFDJSONDataSets (Result) object
TFDJSONDataSetsWriter.ListAdd(Result, sXMLResumo, QueryPesquisa);
//Closing the Query
QueryPesquisa.Close;
//Closing the Connection
oSM.FDConn.Close;
end;`
Basically, the _DataSet is only receiving a JSON List here: _DataSet := TFDJSONDataSetsReader.GetListValueByName( _DataSetJSON, sXMLResumo );, and then open it to access the data in it.

Setting "Server" programmatically with a TFDConnection

TFDConnection.Params.Server is not a valid published property in Delphi XE7. How can I set the server location programmatically? I have 2 MySQL servers (test and production) that are at different ip's and based on what I am doing in the application, I want to easily switch back and forth between the 2 servers.
Please read the documentation, it tells you exactly how to define a FireDAC connection for MySQL:
Working with Connections (FireDAC)
Connect to MySQL Server (FireDAC)
You would specify the DB server as part of a Connection Definition:
Defining Connection (FireDAC)
Connection Definitions can be defined in an external .ini file, which you can then reference in the TFDManager.ConnectionDefFileName property, or load dynamically using the TFDManager.LoadConnectionDefFile() method.
[MySQL_Connection_1]
DriverID=MySQL
Server=192.168.1.100
...
[MySQL_Connection_2]
DriverID=MySQL
Server=192.168.1.101
...
Or dynamically using the TFDManager.ConnectionDefs property:
var
oDef: IFDStanConnectionDef;
begin
oDef := FDManager.ConnectionDefs.AddConnectionDef;
oDef.Name := 'MySQL_Connection_1';
oDef.DriverID := 'MySQL';
oDef.Server := '192.168.1.100';
...
oDef.Apply;
oDef := FDManager.ConnectionDefs.AddConnectionDef;
oDef.Name := 'MySQL_Connection_2';
oDef.DriverID := 'MySQL';
oDef.Server := '192.168.1.101';
...
oDef.Apply;
var
oParams: TStrings;
begin
oParams := TStringList.Create;
oParams.Add('Server=192.168.1.100');
...
FDManager.AddConnectionDef('MySQL_Connection_1', 'MySQL', oParams);
oParams.Clear;
oParams.Add('Server=192.168.1.101');
...
FDManager.AddConnectionDef('MySQL_Connection_2', 'MySQL', oParams);
Either way, you can then tell TFDConnection which Connection Definition to use to reach each database when needed:
FDConnection1.ConnectionDefName := 'MySQL_Connection_1';
// or: FDConnection1.ConnectionDefName := 'MySQL_Connection_2';
FDConnection1.Connected := True;
Alternatively, you can specify the connection parameters directly in the TFDConnection.Params property if you do not want to pre-define separate connection definitions:
FDConnection1.DriverName := 'MySQL';
FDConnection1.Params.Clear;
FDConnection1.Params.Add('Server=192.168.1.100');
// or: FDConnection1.Params.Values['Server'] := '192.168.1.100';
...
FDConnection1.Connected := True;
Late answer but it's simple to do.
Restating what TLama said in a comment:
The param properties can vary depending on the driver type, so set the driver type to MySQL and then cast the PARAMS as the driver type.
Just do:
(Conn1.Params as TFDPhysMySQLConnectionDefParams).Server := '127.0.0.1';
This way the compiler can verify the param at compile time.
This works for me. Add any additional parameters as needed
var
oParams: TStrings;
begin
oParams := TStringList.Create;
oParams.Add('Server=' + YourServer);
oParams.Add('Database=' + YourDatabase);
oParams.Add('OSAuthent=Yes');
FDManager.AddConnectionDef('CNX1', 'MSSQL', oParams);
FDConnection.ConnectionDefName := 'CNX1';
FDConnection.Connected := true;
if FDConnection.Connected then
ShowMessage('Connected');
oParams.Free;

Unable to connect to mySql database useing just code

I searched here but did not see an answer .
I am using Delphi2010.
I using Devart Mydac to connect to mySql data base .
When i set the Server, Database, Name , Pass in the component it connects no problem.
BUt when I try to connect just with code it give an error.
begin
MyConnection1.Server:='MyServer';
MyConnection1.Database:='MyDatabase';
MyConnection1.Username:='MyUserName';
MyConnection1.Password:='MyPassword';
MyConnection1.Connected:= True;
MyQuery1.Active:= True;
end;
exception class EMySalExcption with message"#28000 Access denied for
user'username#00.00.00.00'(useing passworkd: YES)'.
Why will the code method cause an error ?
Thanks for your help and patience.
I would comment, but I don't think I have the ability to yet. But I concur with Marco, I am not experienced with this language or product, but I wonder, is the database on a remote machine? First try setting the server to the IP and seeing if that works.
I found this configuration online and removed a few things to get to the core
begin
MyConnection1.LoginPrompt := false;
MyConnection1.Username := 'test';
MyConnection1.Password := 'test';
MyConnection1.Database := 'test';
MyConnection1.Server := '127.0.0.1';
MyConnection1.Port := 3306;
MyConnection1.Connect;
end;
One thing I noticed is it has a disable for the LoginPrompt, where as you don't, also it has a port. I would try setting the ip and port number, if that works, then try setting just the port number. If none of that works try the full implementation here and then go backwards in taking things out and setting server back to hostname
begin
MyConnection1.Pooling := true;
MyConnection1.PoolingOptions.MinPoolSize := 1;
MyConnection1.LoginPrompt := false;
MyConnection1.Options.Charset := 'utf8';
MyConnection1.Options.Direct := true;
MyConnection1.Options.UseUnicode := true;
MyConnection1.Username := 'test';
MyConnection1.Password := 'test';
MyConnection1.Database := 'test';
MyConnection1.Server := '127.0.0.1';
MyConnection1.Port := 3306;
MyConnection1.Connect;
end;
referenced from http://forums.devart.com/viewtopic.php?t=12035

Querying MYSQL from an external application (is my code inefficient)?

I have a database that I need to query over and over as fast as possible. My queries execute pretty quickly, but there seems to be some additional lag.
I have a feeling that this lag is due to the fact that I am initiating and de-initiating a connection the connection each time. Is there a way to avoid this?
I am not using libmysql (at least, not directly). I am using the "mysql50" package in Lazarus/FreePascal (similar to delphi), which in turn uses libmysql ( I think ).
I would really appreciate if someone took a look at my code and pointed out (or maybe even fixed ) some inefficiencies.
The purpose of this library is to pass along a query sent from MQL4 (a propitiatory C-like language for the financial exchange market), and return a single row from my MYSQL database (to which it connects through a pipe).
{$CALLING STDCALL}
library D1Query;
{$mode objfpc}{$H+}
uses
cmem,
Windows,
SysUtils,
profs_win32exceptiontrap,
mysql50;
var
sock: PMYSQL;
qmysql: st_mysql;
type
VArray = array[0..100] of Double;
PArray = ^VArray;
procedure InitSQL; stdcall;
begin
mysql_init(PMySQL(#qmysql));
sock :=
mysql_real_connect(PMysql(#qmysql), '.', 'root', 'password', 'data', 3306, 'mysql', CLIENT_MULTI_STATEMENTS);
if sock = nil then
begin
OutputDebugString(PChar(' Couldn''t connect to MySQL.'));
OutputDebugString(PChar(mysql_error(#qmysql)));
halt(1);
end;
end;
procedure DeInitSQL; stdcall;
begin
mysql_close(sock);
end;
function SQL_Query(QRY: PChar; output: PArray): integer; stdcall;
var
rowbuf: MYSQL_ROW;
recbuf: PMYSQL_RES;
i: integer;
nfields: LongWord;
begin
InitSQL();
if (mysql_query(sock, QRY) < 0) then
begin
OutputDebugString(PChar(' Query failed '));
OutputDebugString(PChar(' ' + mysql_error(sock)));
end;
recbuf := mysql_store_result(sock);
nfields := mysql_num_fields(recbuf);
rowbuf := mysql_fetch_row(recbuf);
if (rowbuf <> nil) then
begin
for i:=0 to nfields-1 do
output^[i] := StrToFloatDef(rowbuf[i], -666);
end;
mysql_free_result(recbuf);
DeInitSQL();
Result := i;
end;
exports
SQL_Query,
InitSQL,
DeInitSQL;
begin
end.
You could use Initialization and Finalization blocks to handle setting up and tearing down the SQL connection. That way you remove the overhead of connection setup from each query that you execute. You can find more info on Initialization and Finalization here.
From the link:
The initialization block is used to initialize certain variables or execute code that is necessary for the correct functioning of the unit. The initialization parts of the units are executed in the order that the compiler loaded the units when compiling a program. They are executed before the first statement of the program is executed.
The finalization part of the units are executed in the reverse order of the initialization execution. They are used for instance to clean up any resources allocated in the initialization part of the unit, or during the lifetime of the program. The finalization part is always executed in the case of a normal program termination: whether it is because the final end is reached in the program code or because a Halt instruction was executed somewhere.